1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Matthias Hildenbrand, Manuel Jander
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: USAC LPC/AVQ decode
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker #include "usacdec_lpc.h"
104*e5436536SAndroid Build Coastguard Worker
105*e5436536SAndroid Build Coastguard Worker #include "usacdec_rom.h"
106*e5436536SAndroid Build Coastguard Worker #include "FDK_trigFcts.h"
107*e5436536SAndroid Build Coastguard Worker
108*e5436536SAndroid Build Coastguard Worker #define NQ_MAX 36
109*e5436536SAndroid Build Coastguard Worker
110*e5436536SAndroid Build Coastguard Worker /*
111*e5436536SAndroid Build Coastguard Worker * Helper functions.
112*e5436536SAndroid Build Coastguard Worker */
113*e5436536SAndroid Build Coastguard Worker
114*e5436536SAndroid Build Coastguard Worker /**
115*e5436536SAndroid Build Coastguard Worker * \brief Read unary code.
116*e5436536SAndroid Build Coastguard Worker * \param hBs bitstream handle as data source.
117*e5436536SAndroid Build Coastguard Worker * \return decoded value.
118*e5436536SAndroid Build Coastguard Worker */
get_vlclbf(HANDLE_FDK_BITSTREAM hBs)119*e5436536SAndroid Build Coastguard Worker static int get_vlclbf(HANDLE_FDK_BITSTREAM hBs) {
120*e5436536SAndroid Build Coastguard Worker int result = 0;
121*e5436536SAndroid Build Coastguard Worker
122*e5436536SAndroid Build Coastguard Worker while (FDKreadBits(hBs, 1) && result <= NQ_MAX) {
123*e5436536SAndroid Build Coastguard Worker result++;
124*e5436536SAndroid Build Coastguard Worker }
125*e5436536SAndroid Build Coastguard Worker return result;
126*e5436536SAndroid Build Coastguard Worker }
127*e5436536SAndroid Build Coastguard Worker
128*e5436536SAndroid Build Coastguard Worker /**
129*e5436536SAndroid Build Coastguard Worker * \brief Read bit count limited unary code.
130*e5436536SAndroid Build Coastguard Worker * \param hBs bitstream handle as data source
131*e5436536SAndroid Build Coastguard Worker * \param n max amount of bits to be read.
132*e5436536SAndroid Build Coastguard Worker * \return decoded value.
133*e5436536SAndroid Build Coastguard Worker */
get_vlclbf_n(HANDLE_FDK_BITSTREAM hBs,int n)134*e5436536SAndroid Build Coastguard Worker static int get_vlclbf_n(HANDLE_FDK_BITSTREAM hBs, int n) {
135*e5436536SAndroid Build Coastguard Worker int result = 0;
136*e5436536SAndroid Build Coastguard Worker
137*e5436536SAndroid Build Coastguard Worker while (FDKreadBits(hBs, 1)) {
138*e5436536SAndroid Build Coastguard Worker result++;
139*e5436536SAndroid Build Coastguard Worker n--;
140*e5436536SAndroid Build Coastguard Worker if (n <= 0) {
141*e5436536SAndroid Build Coastguard Worker break;
142*e5436536SAndroid Build Coastguard Worker }
143*e5436536SAndroid Build Coastguard Worker }
144*e5436536SAndroid Build Coastguard Worker
145*e5436536SAndroid Build Coastguard Worker return result;
146*e5436536SAndroid Build Coastguard Worker }
147*e5436536SAndroid Build Coastguard Worker
148*e5436536SAndroid Build Coastguard Worker /*
149*e5436536SAndroid Build Coastguard Worker * Algebraic Vector Quantizer
150*e5436536SAndroid Build Coastguard Worker */
151*e5436536SAndroid Build Coastguard Worker
152*e5436536SAndroid Build Coastguard Worker /* ZF_SCALE must be greater than (number of FIXP_ZF)/2
153*e5436536SAndroid Build Coastguard Worker because the loss of precision caused by fPow2Div2 in RE8_PPV() */
154*e5436536SAndroid Build Coastguard Worker //#define ZF_SCALE ((NQ_MAX-3)>>1)
155*e5436536SAndroid Build Coastguard Worker #define ZF_SCALE ((DFRACT_BITS / 2))
156*e5436536SAndroid Build Coastguard Worker #define FIXP_ZF FIXP_DBL
157*e5436536SAndroid Build Coastguard Worker #define INT2ZF(x, s) (FIXP_ZF)((x) << (ZF_SCALE - (s)))
158*e5436536SAndroid Build Coastguard Worker #define ZF2INT(x) (INT)((x) >> ZF_SCALE)
159*e5436536SAndroid Build Coastguard Worker
160*e5436536SAndroid Build Coastguard Worker /* 1.0 in ZF format format */
161*e5436536SAndroid Build Coastguard Worker #define ONEZF ((FIXP_ZF)INT2ZF(1, 0))
162*e5436536SAndroid Build Coastguard Worker
163*e5436536SAndroid Build Coastguard Worker /* static */
nearest_neighbor_2D8(FIXP_ZF x[8],int y[8])164*e5436536SAndroid Build Coastguard Worker void nearest_neighbor_2D8(FIXP_ZF x[8], int y[8]) {
165*e5436536SAndroid Build Coastguard Worker FIXP_ZF s, em, e[8];
166*e5436536SAndroid Build Coastguard Worker int i, j, sum;
167*e5436536SAndroid Build Coastguard Worker
168*e5436536SAndroid Build Coastguard Worker /* round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2]
169*e5436536SAndroid Build Coastguard Worker where [.] is the nearest integer operator
170*e5436536SAndroid Build Coastguard Worker in the mean time, compute sum = y1+...+y8
171*e5436536SAndroid Build Coastguard Worker */
172*e5436536SAndroid Build Coastguard Worker sum = 0;
173*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
174*e5436536SAndroid Build Coastguard Worker FIXP_ZF tmp;
175*e5436536SAndroid Build Coastguard Worker /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */
176*e5436536SAndroid Build Coastguard Worker if (x[i] < (FIXP_ZF)0) {
177*e5436536SAndroid Build Coastguard Worker tmp = ONEZF - x[i];
178*e5436536SAndroid Build Coastguard Worker y[i] = -2 * ((ZF2INT(tmp)) >> 1);
179*e5436536SAndroid Build Coastguard Worker } else {
180*e5436536SAndroid Build Coastguard Worker tmp = ONEZF + x[i];
181*e5436536SAndroid Build Coastguard Worker y[i] = 2 * ((ZF2INT(tmp)) >> 1);
182*e5436536SAndroid Build Coastguard Worker }
183*e5436536SAndroid Build Coastguard Worker sum += y[i];
184*e5436536SAndroid Build Coastguard Worker }
185*e5436536SAndroid Build Coastguard Worker /* check if y1+...+y8 is a multiple of 4
186*e5436536SAndroid Build Coastguard Worker if not, y is not round xj in the wrong way where j is defined by
187*e5436536SAndroid Build Coastguard Worker j = arg max_i | xi -yi|
188*e5436536SAndroid Build Coastguard Worker (this is called the Wagner rule)
189*e5436536SAndroid Build Coastguard Worker */
190*e5436536SAndroid Build Coastguard Worker if (sum % 4) {
191*e5436536SAndroid Build Coastguard Worker /* find j = arg max_i | xi -yi| */
192*e5436536SAndroid Build Coastguard Worker em = (FIXP_SGL)0;
193*e5436536SAndroid Build Coastguard Worker j = 0;
194*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
195*e5436536SAndroid Build Coastguard Worker /* compute ei = xi-yi */
196*e5436536SAndroid Build Coastguard Worker e[i] = x[i] - INT2ZF(y[i], 0);
197*e5436536SAndroid Build Coastguard Worker }
198*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
199*e5436536SAndroid Build Coastguard Worker /* compute |ei| = | xi-yi | */
200*e5436536SAndroid Build Coastguard Worker if (e[i] < (FIXP_ZF)0) {
201*e5436536SAndroid Build Coastguard Worker s = -e[i];
202*e5436536SAndroid Build Coastguard Worker } else {
203*e5436536SAndroid Build Coastguard Worker s = e[i];
204*e5436536SAndroid Build Coastguard Worker }
205*e5436536SAndroid Build Coastguard Worker /* check if |ei| is maximal, if so, set j=i */
206*e5436536SAndroid Build Coastguard Worker if (em < s) {
207*e5436536SAndroid Build Coastguard Worker em = s;
208*e5436536SAndroid Build Coastguard Worker j = i;
209*e5436536SAndroid Build Coastguard Worker }
210*e5436536SAndroid Build Coastguard Worker }
211*e5436536SAndroid Build Coastguard Worker /* round xj in the "wrong way" */
212*e5436536SAndroid Build Coastguard Worker if (e[j] < (FIXP_ZF)0) {
213*e5436536SAndroid Build Coastguard Worker y[j] -= 2;
214*e5436536SAndroid Build Coastguard Worker } else {
215*e5436536SAndroid Build Coastguard Worker y[j] += 2;
216*e5436536SAndroid Build Coastguard Worker }
217*e5436536SAndroid Build Coastguard Worker }
218*e5436536SAndroid Build Coastguard Worker }
219*e5436536SAndroid Build Coastguard Worker
220*e5436536SAndroid Build Coastguard Worker /*--------------------------------------------------------------
221*e5436536SAndroid Build Coastguard Worker RE8_PPV(x,y)
222*e5436536SAndroid Build Coastguard Worker NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8
223*e5436536SAndroid Build Coastguard Worker the algorithm is based on the definition of RE8 as
224*e5436536SAndroid Build Coastguard Worker RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1])
225*e5436536SAndroid Build Coastguard Worker it applies the coset decoding of Sloane and Conway
226*e5436536SAndroid Build Coastguard Worker (i) x: point in R^8 in 32-ZF_SCALE.ZF_SCALE format
227*e5436536SAndroid Build Coastguard Worker (o) y: point in RE8 (8-dimensional integer vector)
228*e5436536SAndroid Build Coastguard Worker --------------------------------------------------------------
229*e5436536SAndroid Build Coastguard Worker */
230*e5436536SAndroid Build Coastguard Worker /* static */
RE8_PPV(FIXP_ZF x[],SHORT y[],int r)231*e5436536SAndroid Build Coastguard Worker void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) {
232*e5436536SAndroid Build Coastguard Worker int i, y0[8], y1[8];
233*e5436536SAndroid Build Coastguard Worker FIXP_ZF x1[8], tmp;
234*e5436536SAndroid Build Coastguard Worker INT64 e;
235*e5436536SAndroid Build Coastguard Worker
236*e5436536SAndroid Build Coastguard Worker /* find the nearest neighbor y0 of x in 2D8 */
237*e5436536SAndroid Build Coastguard Worker nearest_neighbor_2D8(x, y0);
238*e5436536SAndroid Build Coastguard Worker /* find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) */
239*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
240*e5436536SAndroid Build Coastguard Worker x1[i] = x[i] - ONEZF;
241*e5436536SAndroid Build Coastguard Worker }
242*e5436536SAndroid Build Coastguard Worker nearest_neighbor_2D8(x1, y1);
243*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
244*e5436536SAndroid Build Coastguard Worker y1[i] += 1;
245*e5436536SAndroid Build Coastguard Worker }
246*e5436536SAndroid Build Coastguard Worker
247*e5436536SAndroid Build Coastguard Worker /* compute e0=||x-y0||^2 and e1=||x-y1||^2 */
248*e5436536SAndroid Build Coastguard Worker e = 0;
249*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
250*e5436536SAndroid Build Coastguard Worker tmp = x[i] - INT2ZF(y0[i], 0);
251*e5436536SAndroid Build Coastguard Worker e += (INT64)fPow2Div2(
252*e5436536SAndroid Build Coastguard Worker tmp << r); /* shift left to ensure that no fract part bits get lost. */
253*e5436536SAndroid Build Coastguard Worker tmp = x[i] - INT2ZF(y1[i], 0);
254*e5436536SAndroid Build Coastguard Worker e -= (INT64)fPow2Div2(tmp << r);
255*e5436536SAndroid Build Coastguard Worker }
256*e5436536SAndroid Build Coastguard Worker /* select best candidate y0 or y1 to minimize distortion */
257*e5436536SAndroid Build Coastguard Worker if (e < 0) {
258*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
259*e5436536SAndroid Build Coastguard Worker y[i] = y0[i];
260*e5436536SAndroid Build Coastguard Worker }
261*e5436536SAndroid Build Coastguard Worker } else {
262*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
263*e5436536SAndroid Build Coastguard Worker y[i] = y1[i];
264*e5436536SAndroid Build Coastguard Worker }
265*e5436536SAndroid Build Coastguard Worker }
266*e5436536SAndroid Build Coastguard Worker }
267*e5436536SAndroid Build Coastguard Worker
268*e5436536SAndroid Build Coastguard Worker /* table look-up of unsigned value: find i where index >= table[i]
269*e5436536SAndroid Build Coastguard Worker Note: range must be >= 2, index must be >= table[0] */
table_lookup(const USHORT * table,unsigned int index,int range)270*e5436536SAndroid Build Coastguard Worker static int table_lookup(const USHORT *table, unsigned int index, int range) {
271*e5436536SAndroid Build Coastguard Worker int i;
272*e5436536SAndroid Build Coastguard Worker
273*e5436536SAndroid Build Coastguard Worker for (i = 4; i < range; i += 4) {
274*e5436536SAndroid Build Coastguard Worker if (index < table[i]) {
275*e5436536SAndroid Build Coastguard Worker break;
276*e5436536SAndroid Build Coastguard Worker }
277*e5436536SAndroid Build Coastguard Worker }
278*e5436536SAndroid Build Coastguard Worker if (i > range) {
279*e5436536SAndroid Build Coastguard Worker i = range;
280*e5436536SAndroid Build Coastguard Worker }
281*e5436536SAndroid Build Coastguard Worker
282*e5436536SAndroid Build Coastguard Worker if (index < table[i - 2]) {
283*e5436536SAndroid Build Coastguard Worker i -= 2;
284*e5436536SAndroid Build Coastguard Worker }
285*e5436536SAndroid Build Coastguard Worker if (index < table[i - 1]) {
286*e5436536SAndroid Build Coastguard Worker i--;
287*e5436536SAndroid Build Coastguard Worker }
288*e5436536SAndroid Build Coastguard Worker i--;
289*e5436536SAndroid Build Coastguard Worker
290*e5436536SAndroid Build Coastguard Worker return (i); /* index >= table[i] */
291*e5436536SAndroid Build Coastguard Worker }
292*e5436536SAndroid Build Coastguard Worker
293*e5436536SAndroid Build Coastguard Worker /*--------------------------------------------------------------------------
294*e5436536SAndroid Build Coastguard Worker re8_decode_rank_of_permutation(rank, xs, x)
295*e5436536SAndroid Build Coastguard Worker DECODING OF THE RANK OF THE PERMUTATION OF xs
296*e5436536SAndroid Build Coastguard Worker (i) rank: index (rank) of a permutation
297*e5436536SAndroid Build Coastguard Worker (i) xs: signed leader in RE8 (8-dimensional integer vector)
298*e5436536SAndroid Build Coastguard Worker (o) x: point in RE8 (8-dimensional integer vector)
299*e5436536SAndroid Build Coastguard Worker --------------------------------------------------------------------------
300*e5436536SAndroid Build Coastguard Worker */
re8_decode_rank_of_permutation(int rank,int * xs,SHORT x[8])301*e5436536SAndroid Build Coastguard Worker static void re8_decode_rank_of_permutation(int rank, int *xs, SHORT x[8]) {
302*e5436536SAndroid Build Coastguard Worker INT a[8], w[8], B, fac, fac_B, target;
303*e5436536SAndroid Build Coastguard Worker int i, j;
304*e5436536SAndroid Build Coastguard Worker
305*e5436536SAndroid Build Coastguard Worker /* --- pre-processing based on the signed leader xs ---
306*e5436536SAndroid Build Coastguard Worker - compute the alphabet a=[a[0] ... a[q-1]] of x (q elements)
307*e5436536SAndroid Build Coastguard Worker such that a[0]!=...!=a[q-1]
308*e5436536SAndroid Build Coastguard Worker it is assumed that xs is sorted in the form of a signed leader
309*e5436536SAndroid Build Coastguard Worker which can be summarized in 2 requirements:
310*e5436536SAndroid Build Coastguard Worker a) |xs[0]| >= |xs[1]| >= |xs[2]| >= ... >= |xs[7]|
311*e5436536SAndroid Build Coastguard Worker b) if |xs[i]|=|xs[i-1]|, xs[i]>=xs[i+1]
312*e5436536SAndroid Build Coastguard Worker where |.| indicates the absolute value operator
313*e5436536SAndroid Build Coastguard Worker - compute q (the number of symbols in the alphabet)
314*e5436536SAndroid Build Coastguard Worker - compute w[0..q-1] where w[j] counts the number of occurences of
315*e5436536SAndroid Build Coastguard Worker the symbol a[j] in xs
316*e5436536SAndroid Build Coastguard Worker - compute B = prod_j=0..q-1 (w[j]!) where .! is the factorial */
317*e5436536SAndroid Build Coastguard Worker /* xs[i], xs[i-1] and ptr_w/a*/
318*e5436536SAndroid Build Coastguard Worker j = 0;
319*e5436536SAndroid Build Coastguard Worker w[j] = 1;
320*e5436536SAndroid Build Coastguard Worker a[j] = xs[0];
321*e5436536SAndroid Build Coastguard Worker B = 1;
322*e5436536SAndroid Build Coastguard Worker for (i = 1; i < 8; i++) {
323*e5436536SAndroid Build Coastguard Worker if (xs[i] != xs[i - 1]) {
324*e5436536SAndroid Build Coastguard Worker j++;
325*e5436536SAndroid Build Coastguard Worker w[j] = 1;
326*e5436536SAndroid Build Coastguard Worker a[j] = xs[i];
327*e5436536SAndroid Build Coastguard Worker } else {
328*e5436536SAndroid Build Coastguard Worker w[j]++;
329*e5436536SAndroid Build Coastguard Worker B *= w[j];
330*e5436536SAndroid Build Coastguard Worker }
331*e5436536SAndroid Build Coastguard Worker }
332*e5436536SAndroid Build Coastguard Worker
333*e5436536SAndroid Build Coastguard Worker /* --- actual rank decoding ---
334*e5436536SAndroid Build Coastguard Worker the rank of x (where x is a permutation of xs) is based on
335*e5436536SAndroid Build Coastguard Worker Schalkwijk's formula
336*e5436536SAndroid Build Coastguard Worker it is given by rank=sum_{k=0..7} (A_k * fac_k/B_k)
337*e5436536SAndroid Build Coastguard Worker the decoding of this rank is sequential and reconstructs x[0..7]
338*e5436536SAndroid Build Coastguard Worker element by element from x[0] to x[7]
339*e5436536SAndroid Build Coastguard Worker [the tricky part is the inference of A_k for each k...]
340*e5436536SAndroid Build Coastguard Worker */
341*e5436536SAndroid Build Coastguard Worker
342*e5436536SAndroid Build Coastguard Worker if (w[0] == 8) {
343*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
344*e5436536SAndroid Build Coastguard Worker x[i] = a[0]; /* avoid fac of 40320 */
345*e5436536SAndroid Build Coastguard Worker }
346*e5436536SAndroid Build Coastguard Worker } else {
347*e5436536SAndroid Build Coastguard Worker target = rank * B;
348*e5436536SAndroid Build Coastguard Worker fac_B = 1;
349*e5436536SAndroid Build Coastguard Worker /* decode x element by element */
350*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
351*e5436536SAndroid Build Coastguard Worker fac = fac_B * fdk_dec_tab_factorial[i]; /* fac = 1..5040 */
352*e5436536SAndroid Build Coastguard Worker j = -1;
353*e5436536SAndroid Build Coastguard Worker do {
354*e5436536SAndroid Build Coastguard Worker target -= w[++j] * fac;
355*e5436536SAndroid Build Coastguard Worker } while (target >= 0); /* max of 30 tests / SV */
356*e5436536SAndroid Build Coastguard Worker x[i] = a[j];
357*e5436536SAndroid Build Coastguard Worker /* update rank, denominator B (B_k) and counter w[j] */
358*e5436536SAndroid Build Coastguard Worker target += w[j] * fac; /* target = fac_B*B*rank */
359*e5436536SAndroid Build Coastguard Worker fac_B *= w[j];
360*e5436536SAndroid Build Coastguard Worker w[j]--;
361*e5436536SAndroid Build Coastguard Worker }
362*e5436536SAndroid Build Coastguard Worker }
363*e5436536SAndroid Build Coastguard Worker }
364*e5436536SAndroid Build Coastguard Worker
365*e5436536SAndroid Build Coastguard Worker /*--------------------------------------------------------------------------
366*e5436536SAndroid Build Coastguard Worker re8_decode_base_index(n, I, y)
367*e5436536SAndroid Build Coastguard Worker DECODING OF AN INDEX IN Qn (n=0,2,3 or 4)
368*e5436536SAndroid Build Coastguard Worker (i) n: codebook number (*n is an integer defined in {0,2,3,4})
369*e5436536SAndroid Build Coastguard Worker (i) I: index of c (pointer to unsigned 16-bit word)
370*e5436536SAndroid Build Coastguard Worker (o) y: point in RE8 (8-dimensional integer vector)
371*e5436536SAndroid Build Coastguard Worker note: the index I is defined as a 32-bit word, but only
372*e5436536SAndroid Build Coastguard Worker 16 bits are required (long can be replaced by unsigned integer)
373*e5436536SAndroid Build Coastguard Worker --------------------------------------------------------------------------
374*e5436536SAndroid Build Coastguard Worker */
re8_decode_base_index(int * n,UINT index,SHORT y[8])375*e5436536SAndroid Build Coastguard Worker static void re8_decode_base_index(int *n, UINT index, SHORT y[8]) {
376*e5436536SAndroid Build Coastguard Worker int i, im, t, sign_code, ka, ks, rank, leader[8];
377*e5436536SAndroid Build Coastguard Worker
378*e5436536SAndroid Build Coastguard Worker if (*n < 2) {
379*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
380*e5436536SAndroid Build Coastguard Worker y[i] = 0;
381*e5436536SAndroid Build Coastguard Worker }
382*e5436536SAndroid Build Coastguard Worker } else {
383*e5436536SAndroid Build Coastguard Worker // index = (unsigned int)*I;
384*e5436536SAndroid Build Coastguard Worker /* search for the identifier ka of the absolute leader (table-lookup)
385*e5436536SAndroid Build Coastguard Worker Q2 is a subset of Q3 - the two cases are considered in the same branch
386*e5436536SAndroid Build Coastguard Worker */
387*e5436536SAndroid Build Coastguard Worker switch (*n) {
388*e5436536SAndroid Build Coastguard Worker case 2:
389*e5436536SAndroid Build Coastguard Worker case 3:
390*e5436536SAndroid Build Coastguard Worker i = table_lookup(fdk_dec_I3, index, NB_LDQ3);
391*e5436536SAndroid Build Coastguard Worker ka = fdk_dec_A3[i];
392*e5436536SAndroid Build Coastguard Worker break;
393*e5436536SAndroid Build Coastguard Worker case 4:
394*e5436536SAndroid Build Coastguard Worker i = table_lookup(fdk_dec_I4, index, NB_LDQ4);
395*e5436536SAndroid Build Coastguard Worker ka = fdk_dec_A4[i];
396*e5436536SAndroid Build Coastguard Worker break;
397*e5436536SAndroid Build Coastguard Worker default:
398*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
399*e5436536SAndroid Build Coastguard Worker return;
400*e5436536SAndroid Build Coastguard Worker }
401*e5436536SAndroid Build Coastguard Worker /* reconstruct the absolute leader */
402*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
403*e5436536SAndroid Build Coastguard Worker leader[i] = fdk_dec_Da[ka][i];
404*e5436536SAndroid Build Coastguard Worker }
405*e5436536SAndroid Build Coastguard Worker /* search for the identifier ks of the signed leader (table look-up)
406*e5436536SAndroid Build Coastguard Worker (this search is focused based on the identifier ka of the absolute
407*e5436536SAndroid Build Coastguard Worker leader)*/
408*e5436536SAndroid Build Coastguard Worker t = fdk_dec_Ia[ka];
409*e5436536SAndroid Build Coastguard Worker im = fdk_dec_Ns[ka];
410*e5436536SAndroid Build Coastguard Worker ks = table_lookup(fdk_dec_Is + t, index, im);
411*e5436536SAndroid Build Coastguard Worker
412*e5436536SAndroid Build Coastguard Worker /* reconstruct the signed leader from its sign code */
413*e5436536SAndroid Build Coastguard Worker sign_code = 2 * fdk_dec_Ds[t + ks];
414*e5436536SAndroid Build Coastguard Worker for (i = 7; i >= 0; i--) {
415*e5436536SAndroid Build Coastguard Worker leader[i] *= (1 - (sign_code & 2));
416*e5436536SAndroid Build Coastguard Worker sign_code >>= 1;
417*e5436536SAndroid Build Coastguard Worker }
418*e5436536SAndroid Build Coastguard Worker
419*e5436536SAndroid Build Coastguard Worker /* compute and decode the rank of the permutation */
420*e5436536SAndroid Build Coastguard Worker rank = index - fdk_dec_Is[t + ks]; /* rank = index - cardinality offset */
421*e5436536SAndroid Build Coastguard Worker
422*e5436536SAndroid Build Coastguard Worker re8_decode_rank_of_permutation(rank, leader, y);
423*e5436536SAndroid Build Coastguard Worker }
424*e5436536SAndroid Build Coastguard Worker return;
425*e5436536SAndroid Build Coastguard Worker }
426*e5436536SAndroid Build Coastguard Worker
427*e5436536SAndroid Build Coastguard Worker /* re8_y2k(y,m,k)
428*e5436536SAndroid Build Coastguard Worker VORONOI INDEXING (INDEX DECODING) k -> y
429*e5436536SAndroid Build Coastguard Worker (i) k: Voronoi index k[0..7]
430*e5436536SAndroid Build Coastguard Worker (i) m: Voronoi modulo (m = 2^r = 1<<r, where r is integer >=2)
431*e5436536SAndroid Build Coastguard Worker (i) r: Voronoi order (m = 2^r = 1<<r, where r is integer >=2)
432*e5436536SAndroid Build Coastguard Worker (o) y: 8-dimensional point y[0..7] in RE8
433*e5436536SAndroid Build Coastguard Worker */
re8_k2y(int * k,int r,SHORT * y)434*e5436536SAndroid Build Coastguard Worker static void re8_k2y(int *k, int r, SHORT *y) {
435*e5436536SAndroid Build Coastguard Worker int i, tmp, sum;
436*e5436536SAndroid Build Coastguard Worker SHORT v[8];
437*e5436536SAndroid Build Coastguard Worker FIXP_ZF zf[8];
438*e5436536SAndroid Build Coastguard Worker
439*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(r <= ZF_SCALE);
440*e5436536SAndroid Build Coastguard Worker
441*e5436536SAndroid Build Coastguard Worker /* compute y = k M and z=(y-a)/m, where
442*e5436536SAndroid Build Coastguard Worker M = [4 ]
443*e5436536SAndroid Build Coastguard Worker [2 2 ]
444*e5436536SAndroid Build Coastguard Worker [| \ ]
445*e5436536SAndroid Build Coastguard Worker [2 2 ]
446*e5436536SAndroid Build Coastguard Worker [1 1 _ 1 1]
447*e5436536SAndroid Build Coastguard Worker a=(2,0,...,0)
448*e5436536SAndroid Build Coastguard Worker m = 1<<r
449*e5436536SAndroid Build Coastguard Worker */
450*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
451*e5436536SAndroid Build Coastguard Worker y[i] = k[7];
452*e5436536SAndroid Build Coastguard Worker }
453*e5436536SAndroid Build Coastguard Worker zf[7] = INT2ZF(y[7], r);
454*e5436536SAndroid Build Coastguard Worker sum = 0;
455*e5436536SAndroid Build Coastguard Worker for (i = 6; i >= 1; i--) {
456*e5436536SAndroid Build Coastguard Worker tmp = 2 * k[i];
457*e5436536SAndroid Build Coastguard Worker sum += tmp;
458*e5436536SAndroid Build Coastguard Worker y[i] += tmp;
459*e5436536SAndroid Build Coastguard Worker zf[i] = INT2ZF(y[i], r);
460*e5436536SAndroid Build Coastguard Worker }
461*e5436536SAndroid Build Coastguard Worker y[0] += (4 * k[0] + sum);
462*e5436536SAndroid Build Coastguard Worker zf[0] = INT2ZF(y[0] - 2, r);
463*e5436536SAndroid Build Coastguard Worker /* find nearest neighbor v of z in infinite RE8 */
464*e5436536SAndroid Build Coastguard Worker RE8_PPV(zf, v, r);
465*e5436536SAndroid Build Coastguard Worker /* compute y -= m v */
466*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
467*e5436536SAndroid Build Coastguard Worker y[i] -= (SHORT)(v[i] << r);
468*e5436536SAndroid Build Coastguard Worker }
469*e5436536SAndroid Build Coastguard Worker }
470*e5436536SAndroid Build Coastguard Worker
471*e5436536SAndroid Build Coastguard Worker /*--------------------------------------------------------------------------
472*e5436536SAndroid Build Coastguard Worker RE8_dec(n, I, k, y)
473*e5436536SAndroid Build Coastguard Worker MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING)
474*e5436536SAndroid Build Coastguard Worker (i) n: codebook number (*n is an integer defined in {0,2,3,4,..,n_max}). n_max
475*e5436536SAndroid Build Coastguard Worker = 36 (i) I: index of c (pointer to unsigned 16-bit word) (i) k: index of v
476*e5436536SAndroid Build Coastguard Worker (8-dimensional vector of binary indices) = Voronoi index (o) y: point in RE8
477*e5436536SAndroid Build Coastguard Worker (8-dimensional integer vector) note: the index I is defined as a 32-bit word,
478*e5436536SAndroid Build Coastguard Worker but only 16 bits are required (long can be replaced by unsigned integer)
479*e5436536SAndroid Build Coastguard Worker
480*e5436536SAndroid Build Coastguard Worker return 0 on success, -1 on error.
481*e5436536SAndroid Build Coastguard Worker --------------------------------------------------------------------------
482*e5436536SAndroid Build Coastguard Worker */
RE8_dec(int n,int I,int * k,FIXP_DBL * y)483*e5436536SAndroid Build Coastguard Worker static int RE8_dec(int n, int I, int *k, FIXP_DBL *y) {
484*e5436536SAndroid Build Coastguard Worker SHORT v[8];
485*e5436536SAndroid Build Coastguard Worker SHORT _y[8];
486*e5436536SAndroid Build Coastguard Worker UINT r;
487*e5436536SAndroid Build Coastguard Worker int i;
488*e5436536SAndroid Build Coastguard Worker
489*e5436536SAndroid Build Coastguard Worker /* Check bound of codebook qn */
490*e5436536SAndroid Build Coastguard Worker if (n > NQ_MAX) {
491*e5436536SAndroid Build Coastguard Worker return -1;
492*e5436536SAndroid Build Coastguard Worker }
493*e5436536SAndroid Build Coastguard Worker
494*e5436536SAndroid Build Coastguard Worker /* decode the sub-indices I and kv[] according to the codebook number n:
495*e5436536SAndroid Build Coastguard Worker if n=0,2,3,4, decode I (no Voronoi extension)
496*e5436536SAndroid Build Coastguard Worker if n>4, Voronoi extension is used, decode I and kv[] */
497*e5436536SAndroid Build Coastguard Worker if (n <= 4) {
498*e5436536SAndroid Build Coastguard Worker re8_decode_base_index(&n, I, _y);
499*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
500*e5436536SAndroid Build Coastguard Worker y[i] = (LONG)_y[i];
501*e5436536SAndroid Build Coastguard Worker }
502*e5436536SAndroid Build Coastguard Worker } else {
503*e5436536SAndroid Build Coastguard Worker /* compute the Voronoi modulo m = 2^r where r is extension order */
504*e5436536SAndroid Build Coastguard Worker r = ((n - 3) >> 1);
505*e5436536SAndroid Build Coastguard Worker
506*e5436536SAndroid Build Coastguard Worker while (n > 4) {
507*e5436536SAndroid Build Coastguard Worker n -= 2;
508*e5436536SAndroid Build Coastguard Worker }
509*e5436536SAndroid Build Coastguard Worker /* decode base codebook index I into c (c is an element of Q3 or Q4)
510*e5436536SAndroid Build Coastguard Worker [here c is stored in y to save memory] */
511*e5436536SAndroid Build Coastguard Worker re8_decode_base_index(&n, I, _y);
512*e5436536SAndroid Build Coastguard Worker /* decode Voronoi index k[] into v */
513*e5436536SAndroid Build Coastguard Worker re8_k2y(k, r, v);
514*e5436536SAndroid Build Coastguard Worker /* reconstruct y as y = m c + v (with m=2^r, r integer >=1) */
515*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
516*e5436536SAndroid Build Coastguard Worker y[i] = (LONG)((_y[i] << r) + v[i]);
517*e5436536SAndroid Build Coastguard Worker }
518*e5436536SAndroid Build Coastguard Worker }
519*e5436536SAndroid Build Coastguard Worker return 0;
520*e5436536SAndroid Build Coastguard Worker }
521*e5436536SAndroid Build Coastguard Worker
522*e5436536SAndroid Build Coastguard Worker /**************************/
523*e5436536SAndroid Build Coastguard Worker /* start LPC decode stuff */
524*e5436536SAndroid Build Coastguard Worker /**************************/
525*e5436536SAndroid Build Coastguard Worker //#define M 16
526*e5436536SAndroid Build Coastguard Worker #define FREQ_MAX 6400.0f
527*e5436536SAndroid Build Coastguard Worker #define FREQ_DIV 400.0f
528*e5436536SAndroid Build Coastguard Worker #define LSF_GAP 50.0f
529*e5436536SAndroid Build Coastguard Worker
530*e5436536SAndroid Build Coastguard Worker /**
531*e5436536SAndroid Build Coastguard Worker * \brief calculate inverse weighting factor and add non-weighted residual
532*e5436536SAndroid Build Coastguard Worker * LSF vector to first stage LSF approximation
533*e5436536SAndroid Build Coastguard Worker * \param lsfq first stage LSF approximation values.
534*e5436536SAndroid Build Coastguard Worker * \param xq weighted residual LSF vector
535*e5436536SAndroid Build Coastguard Worker * \param nk_mode code book number coding mode.
536*e5436536SAndroid Build Coastguard Worker */
lsf_weight_2st(FIXP_LPC * lsfq,FIXP_DBL * xq,int nk_mode)537*e5436536SAndroid Build Coastguard Worker static void lsf_weight_2st(FIXP_LPC *lsfq, FIXP_DBL *xq, int nk_mode) {
538*e5436536SAndroid Build Coastguard Worker FIXP_LPC d[M_LP_FILTER_ORDER + 1];
539*e5436536SAndroid Build Coastguard Worker FIXP_SGL factor;
540*e5436536SAndroid Build Coastguard Worker LONG w; /* inverse weight factor */
541*e5436536SAndroid Build Coastguard Worker int i;
542*e5436536SAndroid Build Coastguard Worker
543*e5436536SAndroid Build Coastguard Worker /* compute lsf distance */
544*e5436536SAndroid Build Coastguard Worker d[0] = lsfq[0];
545*e5436536SAndroid Build Coastguard Worker d[M_LP_FILTER_ORDER] =
546*e5436536SAndroid Build Coastguard Worker FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - lsfq[M_LP_FILTER_ORDER - 1];
547*e5436536SAndroid Build Coastguard Worker for (i = 1; i < M_LP_FILTER_ORDER; i++) {
548*e5436536SAndroid Build Coastguard Worker d[i] = lsfq[i] - lsfq[i - 1];
549*e5436536SAndroid Build Coastguard Worker }
550*e5436536SAndroid Build Coastguard Worker
551*e5436536SAndroid Build Coastguard Worker switch (nk_mode) {
552*e5436536SAndroid Build Coastguard Worker case 0:
553*e5436536SAndroid Build Coastguard Worker factor = FL2FXCONST_SGL(2.0f * 60.0f / FREQ_DIV);
554*e5436536SAndroid Build Coastguard Worker break; /* abs */
555*e5436536SAndroid Build Coastguard Worker case 1:
556*e5436536SAndroid Build Coastguard Worker factor = FL2FXCONST_SGL(2.0f * 65.0f / FREQ_DIV);
557*e5436536SAndroid Build Coastguard Worker break; /* mid */
558*e5436536SAndroid Build Coastguard Worker case 2:
559*e5436536SAndroid Build Coastguard Worker factor = FL2FXCONST_SGL(2.0f * 64.0f / FREQ_DIV);
560*e5436536SAndroid Build Coastguard Worker break; /* rel1 */
561*e5436536SAndroid Build Coastguard Worker default:
562*e5436536SAndroid Build Coastguard Worker factor = FL2FXCONST_SGL(2.0f * 63.0f / FREQ_DIV);
563*e5436536SAndroid Build Coastguard Worker break; /* rel2 */
564*e5436536SAndroid Build Coastguard Worker }
565*e5436536SAndroid Build Coastguard Worker /* add non-weighted residual LSF vector to LSF1st */
566*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
567*e5436536SAndroid Build Coastguard Worker w = (LONG)fMultDiv2(factor, sqrtFixp(fMult(d[i], d[i + 1])));
568*e5436536SAndroid Build Coastguard Worker lsfq[i] = fAddSaturate(lsfq[i],
569*e5436536SAndroid Build Coastguard Worker FX_DBL2FX_LPC((FIXP_DBL)((INT64)w * (LONG)xq[i])));
570*e5436536SAndroid Build Coastguard Worker }
571*e5436536SAndroid Build Coastguard Worker
572*e5436536SAndroid Build Coastguard Worker return;
573*e5436536SAndroid Build Coastguard Worker }
574*e5436536SAndroid Build Coastguard Worker
575*e5436536SAndroid Build Coastguard Worker /**
576*e5436536SAndroid Build Coastguard Worker * \brief decode nqn amount of code book numbers. These values determine the
577*e5436536SAndroid Build Coastguard Worker * amount of following bits for nqn AVQ RE8 vectors.
578*e5436536SAndroid Build Coastguard Worker * \param nk_mode quantization mode.
579*e5436536SAndroid Build Coastguard Worker * \param nqn amount code book number to read.
580*e5436536SAndroid Build Coastguard Worker * \param qn pointer to output buffer to hold decoded code book numbers qn.
581*e5436536SAndroid Build Coastguard Worker */
decode_qn(HANDLE_FDK_BITSTREAM hBs,int nk_mode,int nqn,int qn[])582*e5436536SAndroid Build Coastguard Worker static void decode_qn(HANDLE_FDK_BITSTREAM hBs, int nk_mode, int nqn,
583*e5436536SAndroid Build Coastguard Worker int qn[]) {
584*e5436536SAndroid Build Coastguard Worker int n;
585*e5436536SAndroid Build Coastguard Worker
586*e5436536SAndroid Build Coastguard Worker if (nk_mode == 1) { /* nk mode 1 */
587*e5436536SAndroid Build Coastguard Worker /* Unary code for mid LPC1/LPC3 */
588*e5436536SAndroid Build Coastguard Worker /* Q0=0, Q2=10, Q3=110, ... */
589*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nqn; n++) {
590*e5436536SAndroid Build Coastguard Worker qn[n] = get_vlclbf(hBs);
591*e5436536SAndroid Build Coastguard Worker if (qn[n] > 0) {
592*e5436536SAndroid Build Coastguard Worker qn[n]++;
593*e5436536SAndroid Build Coastguard Worker }
594*e5436536SAndroid Build Coastguard Worker }
595*e5436536SAndroid Build Coastguard Worker } else { /* nk_mode 0, 3 and 2 */
596*e5436536SAndroid Build Coastguard Worker /* 2 bits to specify Q2,Q3,Q4,ext */
597*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nqn; n++) {
598*e5436536SAndroid Build Coastguard Worker qn[n] = 2 + FDKreadBits(hBs, 2);
599*e5436536SAndroid Build Coastguard Worker }
600*e5436536SAndroid Build Coastguard Worker if (nk_mode == 2) {
601*e5436536SAndroid Build Coastguard Worker /* Unary code for rel LPC1/LPC3 */
602*e5436536SAndroid Build Coastguard Worker /* Q0 = 0, Q5=10, Q6=110, ... */
603*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nqn; n++) {
604*e5436536SAndroid Build Coastguard Worker if (qn[n] > 4) {
605*e5436536SAndroid Build Coastguard Worker qn[n] = get_vlclbf(hBs);
606*e5436536SAndroid Build Coastguard Worker if (qn[n] > 0) qn[n] += 4;
607*e5436536SAndroid Build Coastguard Worker }
608*e5436536SAndroid Build Coastguard Worker }
609*e5436536SAndroid Build Coastguard Worker } else { /* nk_mode == (0 and 3) */
610*e5436536SAndroid Build Coastguard Worker /* Unary code for abs and rel LPC0/LPC2 */
611*e5436536SAndroid Build Coastguard Worker /* Q5 = 0, Q6=10, Q0=110, Q7=1110, ... */
612*e5436536SAndroid Build Coastguard Worker for (n = 0; n < nqn; n++) {
613*e5436536SAndroid Build Coastguard Worker if (qn[n] > 4) {
614*e5436536SAndroid Build Coastguard Worker qn[n] = get_vlclbf(hBs);
615*e5436536SAndroid Build Coastguard Worker switch (qn[n]) {
616*e5436536SAndroid Build Coastguard Worker case 0:
617*e5436536SAndroid Build Coastguard Worker qn[n] = 5;
618*e5436536SAndroid Build Coastguard Worker break;
619*e5436536SAndroid Build Coastguard Worker case 1:
620*e5436536SAndroid Build Coastguard Worker qn[n] = 6;
621*e5436536SAndroid Build Coastguard Worker break;
622*e5436536SAndroid Build Coastguard Worker case 2:
623*e5436536SAndroid Build Coastguard Worker qn[n] = 0;
624*e5436536SAndroid Build Coastguard Worker break;
625*e5436536SAndroid Build Coastguard Worker default:
626*e5436536SAndroid Build Coastguard Worker qn[n] += 4;
627*e5436536SAndroid Build Coastguard Worker break;
628*e5436536SAndroid Build Coastguard Worker }
629*e5436536SAndroid Build Coastguard Worker }
630*e5436536SAndroid Build Coastguard Worker }
631*e5436536SAndroid Build Coastguard Worker }
632*e5436536SAndroid Build Coastguard Worker }
633*e5436536SAndroid Build Coastguard Worker }
634*e5436536SAndroid Build Coastguard Worker
635*e5436536SAndroid Build Coastguard Worker /**
636*e5436536SAndroid Build Coastguard Worker * \brief reorder LSF coefficients to minimum distance.
637*e5436536SAndroid Build Coastguard Worker * \param lsf pointer to buffer containing LSF coefficients and where reordered
638*e5436536SAndroid Build Coastguard Worker * LSF coefficients will be stored into, scaled by LSF_SCALE.
639*e5436536SAndroid Build Coastguard Worker * \param min_dist min distance scaled by LSF_SCALE
640*e5436536SAndroid Build Coastguard Worker * \param n number of LSF/LSP coefficients.
641*e5436536SAndroid Build Coastguard Worker */
reorder_lsf(FIXP_LPC * lsf,FIXP_LPC min_dist,int n)642*e5436536SAndroid Build Coastguard Worker static void reorder_lsf(FIXP_LPC *lsf, FIXP_LPC min_dist, int n) {
643*e5436536SAndroid Build Coastguard Worker FIXP_LPC lsf_min;
644*e5436536SAndroid Build Coastguard Worker int i;
645*e5436536SAndroid Build Coastguard Worker
646*e5436536SAndroid Build Coastguard Worker lsf_min = min_dist;
647*e5436536SAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
648*e5436536SAndroid Build Coastguard Worker if (lsf[i] < lsf_min) {
649*e5436536SAndroid Build Coastguard Worker lsf[i] = lsf_min;
650*e5436536SAndroid Build Coastguard Worker }
651*e5436536SAndroid Build Coastguard Worker lsf_min = fAddSaturate(lsf[i], min_dist);
652*e5436536SAndroid Build Coastguard Worker }
653*e5436536SAndroid Build Coastguard Worker
654*e5436536SAndroid Build Coastguard Worker /* reverse */
655*e5436536SAndroid Build Coastguard Worker lsf_min = FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - min_dist;
656*e5436536SAndroid Build Coastguard Worker for (i = n - 1; i >= 0; i--) {
657*e5436536SAndroid Build Coastguard Worker if (lsf[i] > lsf_min) {
658*e5436536SAndroid Build Coastguard Worker lsf[i] = lsf_min;
659*e5436536SAndroid Build Coastguard Worker }
660*e5436536SAndroid Build Coastguard Worker
661*e5436536SAndroid Build Coastguard Worker lsf_min = lsf[i] - min_dist;
662*e5436536SAndroid Build Coastguard Worker }
663*e5436536SAndroid Build Coastguard Worker }
664*e5436536SAndroid Build Coastguard Worker
665*e5436536SAndroid Build Coastguard Worker /**
666*e5436536SAndroid Build Coastguard Worker * \brief First stage approximation
667*e5436536SAndroid Build Coastguard Worker * \param hBs bitstream handle as data source
668*e5436536SAndroid Build Coastguard Worker * \param lsfq pointer to output buffer to hold LPC coefficients scaled by
669*e5436536SAndroid Build Coastguard Worker * LSF_SCALE.
670*e5436536SAndroid Build Coastguard Worker */
vlpc_1st_dec(HANDLE_FDK_BITSTREAM hBs,FIXP_LPC * lsfq)671*e5436536SAndroid Build Coastguard Worker static void vlpc_1st_dec(
672*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM hBs, /* input: codebook index */
673*e5436536SAndroid Build Coastguard Worker FIXP_LPC *lsfq /* i/o: i:prediction o:quantized lsf */
674*e5436536SAndroid Build Coastguard Worker ) {
675*e5436536SAndroid Build Coastguard Worker const FIXP_LPC *p_dico;
676*e5436536SAndroid Build Coastguard Worker int i, index;
677*e5436536SAndroid Build Coastguard Worker
678*e5436536SAndroid Build Coastguard Worker index = FDKreadBits(hBs, 8);
679*e5436536SAndroid Build Coastguard Worker p_dico = &fdk_dec_dico_lsf_abs_8b[index * M_LP_FILTER_ORDER];
680*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
681*e5436536SAndroid Build Coastguard Worker lsfq[i] = p_dico[i];
682*e5436536SAndroid Build Coastguard Worker }
683*e5436536SAndroid Build Coastguard Worker }
684*e5436536SAndroid Build Coastguard Worker
685*e5436536SAndroid Build Coastguard Worker /**
686*e5436536SAndroid Build Coastguard Worker * \brief Do first stage approximation weighting and multiply with AVQ
687*e5436536SAndroid Build Coastguard Worker * refinement.
688*e5436536SAndroid Build Coastguard Worker * \param hBs bitstream handle data ssource.
689*e5436536SAndroid Build Coastguard Worker * \param lsfq buffer holding 1st stage approx, 2nd stage approx is added to
690*e5436536SAndroid Build Coastguard Worker * this values.
691*e5436536SAndroid Build Coastguard Worker * \param nk_mode quantization mode.
692*e5436536SAndroid Build Coastguard Worker * \return 0 on success, -1 on error.
693*e5436536SAndroid Build Coastguard Worker */
vlpc_2st_dec(HANDLE_FDK_BITSTREAM hBs,FIXP_LPC * lsfq,int nk_mode)694*e5436536SAndroid Build Coastguard Worker static int vlpc_2st_dec(
695*e5436536SAndroid Build Coastguard Worker HANDLE_FDK_BITSTREAM hBs,
696*e5436536SAndroid Build Coastguard Worker FIXP_LPC *lsfq, /* i/o: i:1st stage o:1st+2nd stage */
697*e5436536SAndroid Build Coastguard Worker int nk_mode /* input: 0=abs, >0=rel */
698*e5436536SAndroid Build Coastguard Worker ) {
699*e5436536SAndroid Build Coastguard Worker int err;
700*e5436536SAndroid Build Coastguard Worker FIXP_DBL xq[M_LP_FILTER_ORDER]; /* weighted residual LSF vector */
701*e5436536SAndroid Build Coastguard Worker
702*e5436536SAndroid Build Coastguard Worker /* Decode AVQ refinement */
703*e5436536SAndroid Build Coastguard Worker { err = CLpc_DecodeAVQ(hBs, xq, nk_mode, 2, 8); }
704*e5436536SAndroid Build Coastguard Worker if (err != 0) {
705*e5436536SAndroid Build Coastguard Worker return -1;
706*e5436536SAndroid Build Coastguard Worker }
707*e5436536SAndroid Build Coastguard Worker
708*e5436536SAndroid Build Coastguard Worker /* add non-weighted residual LSF vector to LSF1st */
709*e5436536SAndroid Build Coastguard Worker lsf_weight_2st(lsfq, xq, nk_mode);
710*e5436536SAndroid Build Coastguard Worker
711*e5436536SAndroid Build Coastguard Worker /* reorder */
712*e5436536SAndroid Build Coastguard Worker reorder_lsf(lsfq, FL2FXCONST_LPC(LSF_GAP / (1 << LSF_SCALE)),
713*e5436536SAndroid Build Coastguard Worker M_LP_FILTER_ORDER);
714*e5436536SAndroid Build Coastguard Worker
715*e5436536SAndroid Build Coastguard Worker return 0;
716*e5436536SAndroid Build Coastguard Worker }
717*e5436536SAndroid Build Coastguard Worker
718*e5436536SAndroid Build Coastguard Worker /*
719*e5436536SAndroid Build Coastguard Worker * Externally visible functions
720*e5436536SAndroid Build Coastguard Worker */
721*e5436536SAndroid Build Coastguard Worker
CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs,FIXP_DBL * pOutput,int nk_mode,int no_qn,int length)722*e5436536SAndroid Build Coastguard Worker int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pOutput, int nk_mode,
723*e5436536SAndroid Build Coastguard Worker int no_qn, int length) {
724*e5436536SAndroid Build Coastguard Worker int i, l;
725*e5436536SAndroid Build Coastguard Worker
726*e5436536SAndroid Build Coastguard Worker for (i = 0; i < length; i += 8 * no_qn) {
727*e5436536SAndroid Build Coastguard Worker int qn[2], nk, n, I;
728*e5436536SAndroid Build Coastguard Worker int kv[8] = {0};
729*e5436536SAndroid Build Coastguard Worker
730*e5436536SAndroid Build Coastguard Worker decode_qn(hBs, nk_mode, no_qn, qn);
731*e5436536SAndroid Build Coastguard Worker
732*e5436536SAndroid Build Coastguard Worker for (l = 0; l < no_qn; l++) {
733*e5436536SAndroid Build Coastguard Worker if (qn[l] == 0) {
734*e5436536SAndroid Build Coastguard Worker FDKmemclear(&pOutput[i + l * 8], 8 * sizeof(FIXP_DBL));
735*e5436536SAndroid Build Coastguard Worker }
736*e5436536SAndroid Build Coastguard Worker
737*e5436536SAndroid Build Coastguard Worker /* Voronoi extension order ( nk ) */
738*e5436536SAndroid Build Coastguard Worker nk = 0;
739*e5436536SAndroid Build Coastguard Worker n = qn[l];
740*e5436536SAndroid Build Coastguard Worker if (qn[l] > 4) {
741*e5436536SAndroid Build Coastguard Worker nk = (qn[l] - 3) >> 1;
742*e5436536SAndroid Build Coastguard Worker n = qn[l] - nk * 2;
743*e5436536SAndroid Build Coastguard Worker }
744*e5436536SAndroid Build Coastguard Worker
745*e5436536SAndroid Build Coastguard Worker /* Base codebook index, in reverse bit group order (!) */
746*e5436536SAndroid Build Coastguard Worker I = FDKreadBits(hBs, 4 * n);
747*e5436536SAndroid Build Coastguard Worker
748*e5436536SAndroid Build Coastguard Worker if (nk > 0) {
749*e5436536SAndroid Build Coastguard Worker int j;
750*e5436536SAndroid Build Coastguard Worker
751*e5436536SAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
752*e5436536SAndroid Build Coastguard Worker kv[j] = FDKreadBits(hBs, nk);
753*e5436536SAndroid Build Coastguard Worker }
754*e5436536SAndroid Build Coastguard Worker }
755*e5436536SAndroid Build Coastguard Worker
756*e5436536SAndroid Build Coastguard Worker if (RE8_dec(qn[l], I, kv, &pOutput[i + l * 8]) != 0) {
757*e5436536SAndroid Build Coastguard Worker return -1;
758*e5436536SAndroid Build Coastguard Worker }
759*e5436536SAndroid Build Coastguard Worker }
760*e5436536SAndroid Build Coastguard Worker }
761*e5436536SAndroid Build Coastguard Worker return 0;
762*e5436536SAndroid Build Coastguard Worker }
763*e5436536SAndroid Build Coastguard Worker
CLpc_Read(HANDLE_FDK_BITSTREAM hBs,FIXP_LPC lsp[][M_LP_FILTER_ORDER],FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER],FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER],FIXP_SGL pStability[],UCHAR * mod,int first_lpd_flag,int last_lpc_lost,int last_frame_ok)764*e5436536SAndroid Build Coastguard Worker int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER],
765*e5436536SAndroid Build Coastguard Worker FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER],
766*e5436536SAndroid Build Coastguard Worker FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER],
767*e5436536SAndroid Build Coastguard Worker FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag,
768*e5436536SAndroid Build Coastguard Worker int last_lpc_lost, int last_frame_ok) {
769*e5436536SAndroid Build Coastguard Worker int i, k, err;
770*e5436536SAndroid Build Coastguard Worker int mode_lpc_bin = 0; /* mode_lpc bitstream representation */
771*e5436536SAndroid Build Coastguard Worker int lpc_present[5] = {0, 0, 0, 0, 0};
772*e5436536SAndroid Build Coastguard Worker int lpc0_available = 1;
773*e5436536SAndroid Build Coastguard Worker int s = 0;
774*e5436536SAndroid Build Coastguard Worker int l = 3;
775*e5436536SAndroid Build Coastguard Worker const int nbDiv = NB_DIV;
776*e5436536SAndroid Build Coastguard Worker
777*e5436536SAndroid Build Coastguard Worker lpc_present[4 >> s] = 1; /* LPC4 */
778*e5436536SAndroid Build Coastguard Worker
779*e5436536SAndroid Build Coastguard Worker /* Decode LPC filters in the following order: LPC 4,0,2,1,3 */
780*e5436536SAndroid Build Coastguard Worker
781*e5436536SAndroid Build Coastguard Worker /*** Decode LPC4 ***/
782*e5436536SAndroid Build Coastguard Worker vlpc_1st_dec(hBs, lsp[4 >> s]);
783*e5436536SAndroid Build Coastguard Worker err = vlpc_2st_dec(hBs, lsp[4 >> s], 0); /* nk_mode = 0 */
784*e5436536SAndroid Build Coastguard Worker if (err != 0) {
785*e5436536SAndroid Build Coastguard Worker return err;
786*e5436536SAndroid Build Coastguard Worker }
787*e5436536SAndroid Build Coastguard Worker
788*e5436536SAndroid Build Coastguard Worker /*** Decode LPC0 and LPC2 ***/
789*e5436536SAndroid Build Coastguard Worker k = 0;
790*e5436536SAndroid Build Coastguard Worker if (!first_lpd_flag) {
791*e5436536SAndroid Build Coastguard Worker lpc_present[0] = 1;
792*e5436536SAndroid Build Coastguard Worker lpc0_available = !last_lpc_lost;
793*e5436536SAndroid Build Coastguard Worker /* old LPC4 is new LPC0 */
794*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
795*e5436536SAndroid Build Coastguard Worker lsp[0][i] = lpc4_lsf[i];
796*e5436536SAndroid Build Coastguard Worker }
797*e5436536SAndroid Build Coastguard Worker /* skip LPC0 and continue with LPC2 */
798*e5436536SAndroid Build Coastguard Worker k = 2;
799*e5436536SAndroid Build Coastguard Worker }
800*e5436536SAndroid Build Coastguard Worker
801*e5436536SAndroid Build Coastguard Worker for (; k < l; k += 2) {
802*e5436536SAndroid Build Coastguard Worker int nk_mode = 0;
803*e5436536SAndroid Build Coastguard Worker
804*e5436536SAndroid Build Coastguard Worker if ((k == 2) && (mod[0] == 3)) {
805*e5436536SAndroid Build Coastguard Worker break; /* skip LPC2 */
806*e5436536SAndroid Build Coastguard Worker }
807*e5436536SAndroid Build Coastguard Worker
808*e5436536SAndroid Build Coastguard Worker lpc_present[k >> s] = 1;
809*e5436536SAndroid Build Coastguard Worker
810*e5436536SAndroid Build Coastguard Worker mode_lpc_bin = FDKreadBit(hBs);
811*e5436536SAndroid Build Coastguard Worker
812*e5436536SAndroid Build Coastguard Worker if (mode_lpc_bin == 0) {
813*e5436536SAndroid Build Coastguard Worker /* LPC0/LPC2: Abs */
814*e5436536SAndroid Build Coastguard Worker vlpc_1st_dec(hBs, lsp[k >> s]);
815*e5436536SAndroid Build Coastguard Worker } else {
816*e5436536SAndroid Build Coastguard Worker /* LPC0/LPC2: RelR */
817*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
818*e5436536SAndroid Build Coastguard Worker lsp[k >> s][i] = lsp[4 >> s][i];
819*e5436536SAndroid Build Coastguard Worker }
820*e5436536SAndroid Build Coastguard Worker nk_mode = 3;
821*e5436536SAndroid Build Coastguard Worker }
822*e5436536SAndroid Build Coastguard Worker
823*e5436536SAndroid Build Coastguard Worker err = vlpc_2st_dec(hBs, lsp[k >> s], nk_mode);
824*e5436536SAndroid Build Coastguard Worker if (err != 0) {
825*e5436536SAndroid Build Coastguard Worker return err;
826*e5436536SAndroid Build Coastguard Worker }
827*e5436536SAndroid Build Coastguard Worker }
828*e5436536SAndroid Build Coastguard Worker
829*e5436536SAndroid Build Coastguard Worker /*** Decode LPC1 ***/
830*e5436536SAndroid Build Coastguard Worker if (mod[0] < 2) { /* else: skip LPC1 */
831*e5436536SAndroid Build Coastguard Worker lpc_present[1] = 1;
832*e5436536SAndroid Build Coastguard Worker mode_lpc_bin = get_vlclbf_n(hBs, 2);
833*e5436536SAndroid Build Coastguard Worker
834*e5436536SAndroid Build Coastguard Worker switch (mode_lpc_bin) {
835*e5436536SAndroid Build Coastguard Worker case 1:
836*e5436536SAndroid Build Coastguard Worker /* LPC1: abs */
837*e5436536SAndroid Build Coastguard Worker vlpc_1st_dec(hBs, lsp[1]);
838*e5436536SAndroid Build Coastguard Worker err = vlpc_2st_dec(hBs, lsp[1], 0);
839*e5436536SAndroid Build Coastguard Worker if (err != 0) {
840*e5436536SAndroid Build Coastguard Worker return err;
841*e5436536SAndroid Build Coastguard Worker }
842*e5436536SAndroid Build Coastguard Worker break;
843*e5436536SAndroid Build Coastguard Worker case 2:
844*e5436536SAndroid Build Coastguard Worker /* LPC1: mid0 (no second stage AVQ quantizer in this case) */
845*e5436536SAndroid Build Coastguard Worker if (lpc0_available) { /* LPC0/lsf[0] might be zero some times */
846*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
847*e5436536SAndroid Build Coastguard Worker lsp[1][i] = (lsp[0][i] >> 1) + (lsp[2][i] >> 1);
848*e5436536SAndroid Build Coastguard Worker }
849*e5436536SAndroid Build Coastguard Worker } else {
850*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
851*e5436536SAndroid Build Coastguard Worker lsp[1][i] = lsp[2][i];
852*e5436536SAndroid Build Coastguard Worker }
853*e5436536SAndroid Build Coastguard Worker }
854*e5436536SAndroid Build Coastguard Worker break;
855*e5436536SAndroid Build Coastguard Worker case 0:
856*e5436536SAndroid Build Coastguard Worker /* LPC1: RelR */
857*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
858*e5436536SAndroid Build Coastguard Worker lsp[1][i] = lsp[2][i];
859*e5436536SAndroid Build Coastguard Worker }
860*e5436536SAndroid Build Coastguard Worker err = vlpc_2st_dec(hBs, lsp[1], 2 << s);
861*e5436536SAndroid Build Coastguard Worker if (err != 0) {
862*e5436536SAndroid Build Coastguard Worker return err;
863*e5436536SAndroid Build Coastguard Worker }
864*e5436536SAndroid Build Coastguard Worker break;
865*e5436536SAndroid Build Coastguard Worker }
866*e5436536SAndroid Build Coastguard Worker }
867*e5436536SAndroid Build Coastguard Worker
868*e5436536SAndroid Build Coastguard Worker /*** Decode LPC3 ***/
869*e5436536SAndroid Build Coastguard Worker if ((mod[2] < 2)) { /* else: skip LPC3 */
870*e5436536SAndroid Build Coastguard Worker int nk_mode = 0;
871*e5436536SAndroid Build Coastguard Worker lpc_present[3] = 1;
872*e5436536SAndroid Build Coastguard Worker
873*e5436536SAndroid Build Coastguard Worker mode_lpc_bin = get_vlclbf_n(hBs, 3);
874*e5436536SAndroid Build Coastguard Worker
875*e5436536SAndroid Build Coastguard Worker switch (mode_lpc_bin) {
876*e5436536SAndroid Build Coastguard Worker case 1:
877*e5436536SAndroid Build Coastguard Worker /* LPC3: abs */
878*e5436536SAndroid Build Coastguard Worker vlpc_1st_dec(hBs, lsp[3]);
879*e5436536SAndroid Build Coastguard Worker break;
880*e5436536SAndroid Build Coastguard Worker case 0:
881*e5436536SAndroid Build Coastguard Worker /* LPC3: mid */
882*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
883*e5436536SAndroid Build Coastguard Worker lsp[3][i] = (lsp[2][i] >> 1) + (lsp[4][i] >> 1);
884*e5436536SAndroid Build Coastguard Worker }
885*e5436536SAndroid Build Coastguard Worker nk_mode = 1;
886*e5436536SAndroid Build Coastguard Worker break;
887*e5436536SAndroid Build Coastguard Worker case 2:
888*e5436536SAndroid Build Coastguard Worker /* LPC3: relL */
889*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
890*e5436536SAndroid Build Coastguard Worker lsp[3][i] = lsp[2][i];
891*e5436536SAndroid Build Coastguard Worker }
892*e5436536SAndroid Build Coastguard Worker nk_mode = 2;
893*e5436536SAndroid Build Coastguard Worker break;
894*e5436536SAndroid Build Coastguard Worker case 3:
895*e5436536SAndroid Build Coastguard Worker /* LPC3: relR */
896*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
897*e5436536SAndroid Build Coastguard Worker lsp[3][i] = lsp[4][i];
898*e5436536SAndroid Build Coastguard Worker }
899*e5436536SAndroid Build Coastguard Worker nk_mode = 2;
900*e5436536SAndroid Build Coastguard Worker break;
901*e5436536SAndroid Build Coastguard Worker }
902*e5436536SAndroid Build Coastguard Worker err = vlpc_2st_dec(hBs, lsp[3], nk_mode);
903*e5436536SAndroid Build Coastguard Worker if (err != 0) {
904*e5436536SAndroid Build Coastguard Worker return err;
905*e5436536SAndroid Build Coastguard Worker }
906*e5436536SAndroid Build Coastguard Worker }
907*e5436536SAndroid Build Coastguard Worker
908*e5436536SAndroid Build Coastguard Worker if (!lpc0_available && !last_frame_ok) {
909*e5436536SAndroid Build Coastguard Worker /* LPC(0) was lost. Use next available LPC(k) instead */
910*e5436536SAndroid Build Coastguard Worker for (k = 1; k < (nbDiv + 1); k++) {
911*e5436536SAndroid Build Coastguard Worker if (lpc_present[k]) {
912*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
913*e5436536SAndroid Build Coastguard Worker #define LSF_INIT_TILT (0.25f)
914*e5436536SAndroid Build Coastguard Worker if (mod[0] > 0) {
915*e5436536SAndroid Build Coastguard Worker lsp[0][i] = FX_DBL2FX_LPC(
916*e5436536SAndroid Build Coastguard Worker fMult(lsp[k][i], FL2FXCONST_SGL(1.0f - LSF_INIT_TILT)) +
917*e5436536SAndroid Build Coastguard Worker fMult(fdk_dec_lsf_init[i], FL2FXCONST_SGL(LSF_INIT_TILT)));
918*e5436536SAndroid Build Coastguard Worker } else {
919*e5436536SAndroid Build Coastguard Worker lsp[0][i] = lsp[k][i];
920*e5436536SAndroid Build Coastguard Worker }
921*e5436536SAndroid Build Coastguard Worker }
922*e5436536SAndroid Build Coastguard Worker break;
923*e5436536SAndroid Build Coastguard Worker }
924*e5436536SAndroid Build Coastguard Worker }
925*e5436536SAndroid Build Coastguard Worker }
926*e5436536SAndroid Build Coastguard Worker
927*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
928*e5436536SAndroid Build Coastguard Worker lpc4_lsf[i] = lsp[4 >> s][i];
929*e5436536SAndroid Build Coastguard Worker }
930*e5436536SAndroid Build Coastguard Worker
931*e5436536SAndroid Build Coastguard Worker {
932*e5436536SAndroid Build Coastguard Worker FIXP_DBL divFac;
933*e5436536SAndroid Build Coastguard Worker int last, numLpc = 0;
934*e5436536SAndroid Build Coastguard Worker
935*e5436536SAndroid Build Coastguard Worker i = nbDiv;
936*e5436536SAndroid Build Coastguard Worker do {
937*e5436536SAndroid Build Coastguard Worker numLpc += lpc_present[i--];
938*e5436536SAndroid Build Coastguard Worker } while (i >= 0 && numLpc < 3);
939*e5436536SAndroid Build Coastguard Worker
940*e5436536SAndroid Build Coastguard Worker last = i;
941*e5436536SAndroid Build Coastguard Worker
942*e5436536SAndroid Build Coastguard Worker switch (numLpc) {
943*e5436536SAndroid Build Coastguard Worker case 3:
944*e5436536SAndroid Build Coastguard Worker divFac = FL2FXCONST_DBL(1.0f / 3.0f);
945*e5436536SAndroid Build Coastguard Worker break;
946*e5436536SAndroid Build Coastguard Worker case 2:
947*e5436536SAndroid Build Coastguard Worker divFac = FL2FXCONST_DBL(1.0f / 2.0f);
948*e5436536SAndroid Build Coastguard Worker break;
949*e5436536SAndroid Build Coastguard Worker default:
950*e5436536SAndroid Build Coastguard Worker divFac = FL2FXCONST_DBL(1.0f);
951*e5436536SAndroid Build Coastguard Worker break;
952*e5436536SAndroid Build Coastguard Worker }
953*e5436536SAndroid Build Coastguard Worker
954*e5436536SAndroid Build Coastguard Worker /* get the adaptive mean for the next (bad) frame */
955*e5436536SAndroid Build Coastguard Worker for (k = 0; k < M_LP_FILTER_ORDER; k++) {
956*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp = (FIXP_DBL)0;
957*e5436536SAndroid Build Coastguard Worker for (i = nbDiv; i > last; i--) {
958*e5436536SAndroid Build Coastguard Worker if (lpc_present[i]) {
959*e5436536SAndroid Build Coastguard Worker tmp = fMultAdd(tmp >> 1, lsp[i][k], divFac);
960*e5436536SAndroid Build Coastguard Worker }
961*e5436536SAndroid Build Coastguard Worker }
962*e5436536SAndroid Build Coastguard Worker lsf_adaptive_mean_cand[k] = FX_DBL2FX_LPC(tmp);
963*e5436536SAndroid Build Coastguard Worker }
964*e5436536SAndroid Build Coastguard Worker }
965*e5436536SAndroid Build Coastguard Worker
966*e5436536SAndroid Build Coastguard Worker /* calculate stability factor Theta. Needed for ACELP decoder and concealment
967*e5436536SAndroid Build Coastguard Worker */
968*e5436536SAndroid Build Coastguard Worker {
969*e5436536SAndroid Build Coastguard Worker FIXP_LPC *lsf_prev, *lsf_curr;
970*e5436536SAndroid Build Coastguard Worker k = 0;
971*e5436536SAndroid Build Coastguard Worker
972*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(lpc_present[0] == 1 && lpc_present[4 >> s] == 1);
973*e5436536SAndroid Build Coastguard Worker lsf_prev = lsp[0];
974*e5436536SAndroid Build Coastguard Worker for (i = 1; i < (nbDiv + 1); i++) {
975*e5436536SAndroid Build Coastguard Worker if (lpc_present[i]) {
976*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp = (FIXP_DBL)0;
977*e5436536SAndroid Build Coastguard Worker int j;
978*e5436536SAndroid Build Coastguard Worker lsf_curr = lsp[i];
979*e5436536SAndroid Build Coastguard Worker
980*e5436536SAndroid Build Coastguard Worker /* sum = tmp * 2^(LSF_SCALE*2 + 4) */
981*e5436536SAndroid Build Coastguard Worker for (j = 0; j < M_LP_FILTER_ORDER; j++) {
982*e5436536SAndroid Build Coastguard Worker tmp += fPow2Div2((FIXP_SGL)(lsf_curr[j] - lsf_prev[j])) >> 3;
983*e5436536SAndroid Build Coastguard Worker }
984*e5436536SAndroid Build Coastguard Worker
985*e5436536SAndroid Build Coastguard Worker /* tmp = (float)(FL2FXCONST_DBL(1.25f) - fMult(tmp,
986*e5436536SAndroid Build Coastguard Worker * FL2FXCONST_DBL(1/400000.0f))); */
987*e5436536SAndroid Build Coastguard Worker tmp = FL2FXCONST_DBL(1.25f / (1 << LSF_SCALE)) -
988*e5436536SAndroid Build Coastguard Worker fMult(tmp, FL2FXCONST_DBL((1 << (LSF_SCALE + 4)) / 400000.0f));
989*e5436536SAndroid Build Coastguard Worker if (tmp >= FL2FXCONST_DBL(1.0f / (1 << LSF_SCALE))) {
990*e5436536SAndroid Build Coastguard Worker pStability[k] = FL2FXCONST_SGL(1.0f / 2.0f);
991*e5436536SAndroid Build Coastguard Worker } else if (tmp < FL2FXCONST_DBL(0.0f)) {
992*e5436536SAndroid Build Coastguard Worker pStability[k] = FL2FXCONST_SGL(0.0f);
993*e5436536SAndroid Build Coastguard Worker } else {
994*e5436536SAndroid Build Coastguard Worker pStability[k] = FX_DBL2FX_SGL(tmp << (LSF_SCALE - 1));
995*e5436536SAndroid Build Coastguard Worker }
996*e5436536SAndroid Build Coastguard Worker
997*e5436536SAndroid Build Coastguard Worker lsf_prev = lsf_curr;
998*e5436536SAndroid Build Coastguard Worker k = i;
999*e5436536SAndroid Build Coastguard Worker } else {
1000*e5436536SAndroid Build Coastguard Worker /* Mark stability value as undefined. */
1001*e5436536SAndroid Build Coastguard Worker pStability[i] = (FIXP_SGL)-1;
1002*e5436536SAndroid Build Coastguard Worker }
1003*e5436536SAndroid Build Coastguard Worker }
1004*e5436536SAndroid Build Coastguard Worker }
1005*e5436536SAndroid Build Coastguard Worker
1006*e5436536SAndroid Build Coastguard Worker /* convert into LSP domain */
1007*e5436536SAndroid Build Coastguard Worker for (i = 0; i < (nbDiv + 1); i++) {
1008*e5436536SAndroid Build Coastguard Worker if (lpc_present[i]) {
1009*e5436536SAndroid Build Coastguard Worker for (k = 0; k < M_LP_FILTER_ORDER; k++) {
1010*e5436536SAndroid Build Coastguard Worker lsp[i][k] = FX_DBL2FX_LPC(
1011*e5436536SAndroid Build Coastguard Worker fixp_cos(fMult(lsp[i][k],
1012*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)),
1013*e5436536SAndroid Build Coastguard Worker LSF_SCALE - LSPARG_SCALE));
1014*e5436536SAndroid Build Coastguard Worker }
1015*e5436536SAndroid Build Coastguard Worker }
1016*e5436536SAndroid Build Coastguard Worker }
1017*e5436536SAndroid Build Coastguard Worker
1018*e5436536SAndroid Build Coastguard Worker return 0;
1019*e5436536SAndroid Build Coastguard Worker }
1020*e5436536SAndroid Build Coastguard Worker
CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER],FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER],FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER],const int first_lpd_flag)1021*e5436536SAndroid Build Coastguard Worker void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER],
1022*e5436536SAndroid Build Coastguard Worker FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER],
1023*e5436536SAndroid Build Coastguard Worker FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER],
1024*e5436536SAndroid Build Coastguard Worker const int first_lpd_flag) {
1025*e5436536SAndroid Build Coastguard Worker int i, j;
1026*e5436536SAndroid Build Coastguard Worker
1027*e5436536SAndroid Build Coastguard Worker #define BETA (FL2FXCONST_SGL(0.25f))
1028*e5436536SAndroid Build Coastguard Worker #define ONE_BETA (FL2FXCONST_SGL(0.75f))
1029*e5436536SAndroid Build Coastguard Worker #define BFI_FAC (FL2FXCONST_SGL(0.90f))
1030*e5436536SAndroid Build Coastguard Worker #define ONE_BFI_FAC (FL2FXCONST_SGL(0.10f))
1031*e5436536SAndroid Build Coastguard Worker
1032*e5436536SAndroid Build Coastguard Worker /* Frame loss concealment (could be improved) */
1033*e5436536SAndroid Build Coastguard Worker
1034*e5436536SAndroid Build Coastguard Worker if (first_lpd_flag) {
1035*e5436536SAndroid Build Coastguard Worker /* Reset past LSF values */
1036*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1037*e5436536SAndroid Build Coastguard Worker lsp[0][i] = lpc4_lsf[i] = fdk_dec_lsf_init[i];
1038*e5436536SAndroid Build Coastguard Worker }
1039*e5436536SAndroid Build Coastguard Worker } else {
1040*e5436536SAndroid Build Coastguard Worker /* old LPC4 is new LPC0 */
1041*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1042*e5436536SAndroid Build Coastguard Worker lsp[0][i] = lpc4_lsf[i];
1043*e5436536SAndroid Build Coastguard Worker }
1044*e5436536SAndroid Build Coastguard Worker }
1045*e5436536SAndroid Build Coastguard Worker
1046*e5436536SAndroid Build Coastguard Worker /* LPC1 */
1047*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1048*e5436536SAndroid Build Coastguard Worker FIXP_LPC lsf_mean = FX_DBL2FX_LPC(fMult(BETA, fdk_dec_lsf_init[i]) +
1049*e5436536SAndroid Build Coastguard Worker fMult(ONE_BETA, lsf_adaptive_mean[i]));
1050*e5436536SAndroid Build Coastguard Worker
1051*e5436536SAndroid Build Coastguard Worker lsp[1][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lpc4_lsf[i]) +
1052*e5436536SAndroid Build Coastguard Worker fMult(ONE_BFI_FAC, lsf_mean));
1053*e5436536SAndroid Build Coastguard Worker }
1054*e5436536SAndroid Build Coastguard Worker
1055*e5436536SAndroid Build Coastguard Worker /* LPC2 - LPC4 */
1056*e5436536SAndroid Build Coastguard Worker for (j = 2; j <= 4; j++) {
1057*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1058*e5436536SAndroid Build Coastguard Worker /* lsf_mean[i] = FX_DBL2FX_LPC(fMult((FIXP_LPC)(BETA + j *
1059*e5436536SAndroid Build Coastguard Worker FL2FXCONST_LPC(0.1f)), fdk_dec_lsf_init[i])
1060*e5436536SAndroid Build Coastguard Worker + fMult((FIXP_LPC)(ONE_BETA - j *
1061*e5436536SAndroid Build Coastguard Worker FL2FXCONST_LPC(0.1f)), lsf_adaptive_mean[i])); */
1062*e5436536SAndroid Build Coastguard Worker
1063*e5436536SAndroid Build Coastguard Worker FIXP_LPC lsf_mean = FX_DBL2FX_LPC(
1064*e5436536SAndroid Build Coastguard Worker fMult((FIXP_SGL)(BETA + (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))),
1065*e5436536SAndroid Build Coastguard Worker (FIXP_SGL)fdk_dec_lsf_init[i]) +
1066*e5436536SAndroid Build Coastguard Worker fMult(
1067*e5436536SAndroid Build Coastguard Worker (FIXP_SGL)(ONE_BETA - (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))),
1068*e5436536SAndroid Build Coastguard Worker lsf_adaptive_mean[i]));
1069*e5436536SAndroid Build Coastguard Worker
1070*e5436536SAndroid Build Coastguard Worker lsp[j][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lsp[j - 1][i]) +
1071*e5436536SAndroid Build Coastguard Worker fMult(ONE_BFI_FAC, lsf_mean));
1072*e5436536SAndroid Build Coastguard Worker }
1073*e5436536SAndroid Build Coastguard Worker }
1074*e5436536SAndroid Build Coastguard Worker
1075*e5436536SAndroid Build Coastguard Worker /* Update past values for the future */
1076*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1077*e5436536SAndroid Build Coastguard Worker lpc4_lsf[i] = lsp[4][i];
1078*e5436536SAndroid Build Coastguard Worker }
1079*e5436536SAndroid Build Coastguard Worker
1080*e5436536SAndroid Build Coastguard Worker /* convert into LSP domain */
1081*e5436536SAndroid Build Coastguard Worker for (j = 0; j < 5; j++) {
1082*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1083*e5436536SAndroid Build Coastguard Worker lsp[j][i] = FX_DBL2FX_LPC(fixp_cos(
1084*e5436536SAndroid Build Coastguard Worker fMult(lsp[j][i], FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)),
1085*e5436536SAndroid Build Coastguard Worker LSF_SCALE - LSPARG_SCALE));
1086*e5436536SAndroid Build Coastguard Worker }
1087*e5436536SAndroid Build Coastguard Worker }
1088*e5436536SAndroid Build Coastguard Worker }
1089*e5436536SAndroid Build Coastguard Worker
E_LPC_a_weight(FIXP_LPC * wA,const FIXP_LPC * A,int m)1090*e5436536SAndroid Build Coastguard Worker void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, int m) {
1091*e5436536SAndroid Build Coastguard Worker FIXP_DBL f;
1092*e5436536SAndroid Build Coastguard Worker int i;
1093*e5436536SAndroid Build Coastguard Worker
1094*e5436536SAndroid Build Coastguard Worker f = FL2FXCONST_DBL(0.92f);
1095*e5436536SAndroid Build Coastguard Worker for (i = 0; i < m; i++) {
1096*e5436536SAndroid Build Coastguard Worker wA[i] = FX_DBL2FX_LPC(fMult(A[i], f));
1097*e5436536SAndroid Build Coastguard Worker f = fMult(f, FL2FXCONST_DBL(0.92f));
1098*e5436536SAndroid Build Coastguard Worker }
1099*e5436536SAndroid Build Coastguard Worker }
1100*e5436536SAndroid Build Coastguard Worker
CLpd_DecodeGain(FIXP_DBL * gain,INT * gain_e,int gain_code)1101*e5436536SAndroid Build Coastguard Worker void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code) {
1102*e5436536SAndroid Build Coastguard Worker /* gain * 2^(gain_e) = 10^(gain_code/28) */
1103*e5436536SAndroid Build Coastguard Worker *gain = fLdPow(
1104*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(3.3219280948873623478703194294894 / 4.0), /* log2(10)*/
1105*e5436536SAndroid Build Coastguard Worker 2,
1106*e5436536SAndroid Build Coastguard Worker fMultDiv2((FIXP_DBL)gain_code << (DFRACT_BITS - 1 - 7),
1107*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(2.0f / 28.0f)),
1108*e5436536SAndroid Build Coastguard Worker 7, gain_e);
1109*e5436536SAndroid Build Coastguard Worker }
1110*e5436536SAndroid Build Coastguard Worker
1111*e5436536SAndroid Build Coastguard Worker /**
1112*e5436536SAndroid Build Coastguard Worker * \brief * Find the polynomial F1(z) or F2(z) from the LSPs.
1113*e5436536SAndroid Build Coastguard Worker * This is performed by expanding the product polynomials:
1114*e5436536SAndroid Build Coastguard Worker *
1115*e5436536SAndroid Build Coastguard Worker * F1(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 )
1116*e5436536SAndroid Build Coastguard Worker * i=0,2,4,6,8
1117*e5436536SAndroid Build Coastguard Worker * F2(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 )
1118*e5436536SAndroid Build Coastguard Worker * i=1,3,5,7,9
1119*e5436536SAndroid Build Coastguard Worker *
1120*e5436536SAndroid Build Coastguard Worker * where LSP_i are the LSPs in the cosine domain.
1121*e5436536SAndroid Build Coastguard Worker * R.A.Salami October 1990
1122*e5436536SAndroid Build Coastguard Worker * \param lsp input, line spectral freq. (cosine domain)
1123*e5436536SAndroid Build Coastguard Worker * \param f output, the coefficients of F1 or F2, scaled by 8 bits
1124*e5436536SAndroid Build Coastguard Worker * \param n no of coefficients (m/2)
1125*e5436536SAndroid Build Coastguard Worker * \param flag 1 : F1(z) ; 2 : F2(z)
1126*e5436536SAndroid Build Coastguard Worker */
1127*e5436536SAndroid Build Coastguard Worker
1128*e5436536SAndroid Build Coastguard Worker #define SF_F 8
1129*e5436536SAndroid Build Coastguard Worker
get_lsppol(FIXP_LPC lsp[],FIXP_DBL f[],int n,int flag)1130*e5436536SAndroid Build Coastguard Worker static void get_lsppol(FIXP_LPC lsp[], FIXP_DBL f[], int n, int flag) {
1131*e5436536SAndroid Build Coastguard Worker FIXP_DBL b;
1132*e5436536SAndroid Build Coastguard Worker FIXP_LPC *plsp;
1133*e5436536SAndroid Build Coastguard Worker int i, j;
1134*e5436536SAndroid Build Coastguard Worker
1135*e5436536SAndroid Build Coastguard Worker plsp = lsp + flag - 1;
1136*e5436536SAndroid Build Coastguard Worker f[0] = FL2FXCONST_DBL(1.0f / (1 << SF_F));
1137*e5436536SAndroid Build Coastguard Worker b = -FX_LPC2FX_DBL(*plsp);
1138*e5436536SAndroid Build Coastguard Worker f[1] = b >> (SF_F - 1);
1139*e5436536SAndroid Build Coastguard Worker for (i = 2; i <= n; i++) {
1140*e5436536SAndroid Build Coastguard Worker plsp += 2;
1141*e5436536SAndroid Build Coastguard Worker b = -FX_LPC2FX_DBL(*plsp);
1142*e5436536SAndroid Build Coastguard Worker f[i] = SATURATE_LEFT_SHIFT((fMultDiv2(b, f[i - 1]) + (f[i - 2] >> 1)), 2,
1143*e5436536SAndroid Build Coastguard Worker DFRACT_BITS);
1144*e5436536SAndroid Build Coastguard Worker for (j = i - 1; j > 1; j--) {
1145*e5436536SAndroid Build Coastguard Worker f[j] = SATURATE_LEFT_SHIFT(
1146*e5436536SAndroid Build Coastguard Worker ((f[j] >> 2) + fMultDiv2(b, f[j - 1]) + (f[j - 2] >> 2)), 2,
1147*e5436536SAndroid Build Coastguard Worker DFRACT_BITS);
1148*e5436536SAndroid Build Coastguard Worker }
1149*e5436536SAndroid Build Coastguard Worker f[1] = f[1] + (b >> (SF_F - 1));
1150*e5436536SAndroid Build Coastguard Worker }
1151*e5436536SAndroid Build Coastguard Worker return;
1152*e5436536SAndroid Build Coastguard Worker }
1153*e5436536SAndroid Build Coastguard Worker
1154*e5436536SAndroid Build Coastguard Worker #define NC M_LP_FILTER_ORDER / 2
1155*e5436536SAndroid Build Coastguard Worker
1156*e5436536SAndroid Build Coastguard Worker /**
1157*e5436536SAndroid Build Coastguard Worker * \brief lsp input LSP vector
1158*e5436536SAndroid Build Coastguard Worker * \brief a output LP filter coefficient vector scaled by SF_A_COEFFS.
1159*e5436536SAndroid Build Coastguard Worker */
E_LPC_f_lsp_a_conversion(FIXP_LPC * lsp,FIXP_LPC * a,INT * a_exp)1160*e5436536SAndroid Build Coastguard Worker void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) {
1161*e5436536SAndroid Build Coastguard Worker FIXP_DBL f1[NC + 1], f2[NC + 1];
1162*e5436536SAndroid Build Coastguard Worker int i, k;
1163*e5436536SAndroid Build Coastguard Worker
1164*e5436536SAndroid Build Coastguard Worker /*-----------------------------------------------------*
1165*e5436536SAndroid Build Coastguard Worker * Find the polynomials F1(z) and F2(z) *
1166*e5436536SAndroid Build Coastguard Worker *-----------------------------------------------------*/
1167*e5436536SAndroid Build Coastguard Worker
1168*e5436536SAndroid Build Coastguard Worker get_lsppol(lsp, f1, NC, 1);
1169*e5436536SAndroid Build Coastguard Worker get_lsppol(lsp, f2, NC, 2);
1170*e5436536SAndroid Build Coastguard Worker
1171*e5436536SAndroid Build Coastguard Worker /*-----------------------------------------------------*
1172*e5436536SAndroid Build Coastguard Worker * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) *
1173*e5436536SAndroid Build Coastguard Worker *-----------------------------------------------------*/
1174*e5436536SAndroid Build Coastguard Worker scaleValues(f1, NC + 1, -2);
1175*e5436536SAndroid Build Coastguard Worker scaleValues(f2, NC + 1, -2);
1176*e5436536SAndroid Build Coastguard Worker
1177*e5436536SAndroid Build Coastguard Worker for (i = NC; i > 0; i--) {
1178*e5436536SAndroid Build Coastguard Worker f1[i] += f1[i - 1];
1179*e5436536SAndroid Build Coastguard Worker f2[i] -= f2[i - 1];
1180*e5436536SAndroid Build Coastguard Worker }
1181*e5436536SAndroid Build Coastguard Worker
1182*e5436536SAndroid Build Coastguard Worker FIXP_DBL aDBL[M_LP_FILTER_ORDER];
1183*e5436536SAndroid Build Coastguard Worker
1184*e5436536SAndroid Build Coastguard Worker for (i = 1, k = M_LP_FILTER_ORDER - 1; i <= NC; i++, k--) {
1185*e5436536SAndroid Build Coastguard Worker aDBL[i - 1] = f1[i] + f2[i];
1186*e5436536SAndroid Build Coastguard Worker aDBL[k] = f1[i] - f2[i];
1187*e5436536SAndroid Build Coastguard Worker }
1188*e5436536SAndroid Build Coastguard Worker
1189*e5436536SAndroid Build Coastguard Worker int headroom_a = getScalefactor(aDBL, M_LP_FILTER_ORDER);
1190*e5436536SAndroid Build Coastguard Worker
1191*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M_LP_FILTER_ORDER; i++) {
1192*e5436536SAndroid Build Coastguard Worker a[i] = FX_DBL2FX_LPC(aDBL[i] << headroom_a);
1193*e5436536SAndroid Build Coastguard Worker }
1194*e5436536SAndroid Build Coastguard Worker
1195*e5436536SAndroid Build Coastguard Worker *a_exp = SF_F + (2 - 1) - headroom_a;
1196*e5436536SAndroid Build Coastguard Worker }
1197