xref: /aosp_15_r20/external/aac/libFDK/src/FDK_lpc.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 - 2018 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 /******************* Library for basic calculation routines ********************
96*e5436536SAndroid Build Coastguard Worker 
97*e5436536SAndroid Build Coastguard Worker    Author(s):   Manuel Jander
98*e5436536SAndroid Build Coastguard Worker 
99*e5436536SAndroid Build Coastguard Worker    Description: LPC related functions
100*e5436536SAndroid Build Coastguard Worker 
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker 
103*e5436536SAndroid Build Coastguard Worker #include "FDK_lpc.h"
104*e5436536SAndroid Build Coastguard Worker 
105*e5436536SAndroid Build Coastguard Worker /* Internal scaling of LPC synthesis to avoid overflow of filte states.
106*e5436536SAndroid Build Coastguard Worker    This depends on the LPC order, because the LPC order defines the amount
107*e5436536SAndroid Build Coastguard Worker    of MAC operations. */
108*e5436536SAndroid Build Coastguard Worker static SCHAR order_ld[LPC_MAX_ORDER] = {
109*e5436536SAndroid Build Coastguard Worker     /* Assume that Synthesis filter output does not clip and filter
110*e5436536SAndroid Build Coastguard Worker        accu does change no more than 1.0 for each iteration.
111*e5436536SAndroid Build Coastguard Worker        ceil(0.5*log((1:24))/log(2)) */
112*e5436536SAndroid Build Coastguard Worker     0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3};
113*e5436536SAndroid Build Coastguard Worker 
114*e5436536SAndroid Build Coastguard Worker /* IIRLattice */
115*e5436536SAndroid Build Coastguard Worker #ifndef FUNCTION_CLpc_SynthesisLattice_SGL
CLpc_SynthesisLattice(FIXP_DBL * signal,const int signal_size,const int signal_e,const int signal_e_out,const int inc,const FIXP_SGL * coeff,const int order,FIXP_DBL * state)116*e5436536SAndroid Build Coastguard Worker void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size,
117*e5436536SAndroid Build Coastguard Worker                            const int signal_e, const int signal_e_out,
118*e5436536SAndroid Build Coastguard Worker                            const int inc, const FIXP_SGL *coeff,
119*e5436536SAndroid Build Coastguard Worker                            const int order, FIXP_DBL *state) {
120*e5436536SAndroid Build Coastguard Worker   int i, j;
121*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pSignal;
122*e5436536SAndroid Build Coastguard Worker   int shift;
123*e5436536SAndroid Build Coastguard Worker 
124*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order <= LPC_MAX_ORDER);
125*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order > 0);
126*e5436536SAndroid Build Coastguard Worker 
127*e5436536SAndroid Build Coastguard Worker   if (inc == -1)
128*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[signal_size - 1];
129*e5436536SAndroid Build Coastguard Worker   else
130*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[0];
131*e5436536SAndroid Build Coastguard Worker 
132*e5436536SAndroid Build Coastguard Worker   /*
133*e5436536SAndroid Build Coastguard Worker     tmp = x(k) - K(M)*g(M);
134*e5436536SAndroid Build Coastguard Worker     for m=M-1:-1:1
135*e5436536SAndroid Build Coastguard Worker             tmp = tmp - K(m) * g(m);
136*e5436536SAndroid Build Coastguard Worker             g(m+1) = g(m) + K(m) * tmp;
137*e5436536SAndroid Build Coastguard Worker     endfor
138*e5436536SAndroid Build Coastguard Worker     g(1) = tmp;
139*e5436536SAndroid Build Coastguard Worker 
140*e5436536SAndroid Build Coastguard Worker     y(k) = tmp;
141*e5436536SAndroid Build Coastguard Worker   */
142*e5436536SAndroid Build Coastguard Worker 
143*e5436536SAndroid Build Coastguard Worker   shift = -order_ld[order - 1];
144*e5436536SAndroid Build Coastguard Worker 
145*e5436536SAndroid Build Coastguard Worker   for (i = signal_size; i != 0; i--) {
146*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *pState = state + order - 1;
147*e5436536SAndroid Build Coastguard Worker     const FIXP_SGL *pCoeff = coeff + order - 1;
148*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp;
149*e5436536SAndroid Build Coastguard Worker 
150*e5436536SAndroid Build Coastguard Worker     tmp = scaleValue(*pSignal, shift + signal_e) -
151*e5436536SAndroid Build Coastguard Worker           fMultDiv2(*pCoeff--, *pState--);
152*e5436536SAndroid Build Coastguard Worker     for (j = order - 1; j != 0; j--) {
153*e5436536SAndroid Build Coastguard Worker       tmp = fMultSubDiv2(tmp, pCoeff[0], pState[0]);
154*e5436536SAndroid Build Coastguard Worker       pState[1] = pState[0] + (fMultDiv2(*pCoeff--, tmp) << 2);
155*e5436536SAndroid Build Coastguard Worker       pState--;
156*e5436536SAndroid Build Coastguard Worker     }
157*e5436536SAndroid Build Coastguard Worker 
158*e5436536SAndroid Build Coastguard Worker     *pSignal = scaleValueSaturate(tmp, -shift - signal_e_out);
159*e5436536SAndroid Build Coastguard Worker 
160*e5436536SAndroid Build Coastguard Worker     /* exponent of state[] is -1 */
161*e5436536SAndroid Build Coastguard Worker     pState[1] = tmp << 1;
162*e5436536SAndroid Build Coastguard Worker     pSignal += inc;
163*e5436536SAndroid Build Coastguard Worker   }
164*e5436536SAndroid Build Coastguard Worker }
165*e5436536SAndroid Build Coastguard Worker #endif
166*e5436536SAndroid Build Coastguard Worker 
167*e5436536SAndroid Build Coastguard Worker #ifndef FUNCTION_CLpc_SynthesisLattice_DBL
CLpc_SynthesisLattice(FIXP_DBL * signal,const int signal_size,const int signal_e,const int signal_e_out,const int inc,const FIXP_DBL * coeff,const int order,FIXP_DBL * state)168*e5436536SAndroid Build Coastguard Worker void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size,
169*e5436536SAndroid Build Coastguard Worker                            const int signal_e, const int signal_e_out,
170*e5436536SAndroid Build Coastguard Worker                            const int inc, const FIXP_DBL *coeff,
171*e5436536SAndroid Build Coastguard Worker                            const int order, FIXP_DBL *state) {
172*e5436536SAndroid Build Coastguard Worker   int i, j;
173*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pSignal;
174*e5436536SAndroid Build Coastguard Worker 
175*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order <= LPC_MAX_ORDER);
176*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order > 0);
177*e5436536SAndroid Build Coastguard Worker 
178*e5436536SAndroid Build Coastguard Worker   if (inc == -1)
179*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[signal_size - 1];
180*e5436536SAndroid Build Coastguard Worker   else
181*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[0];
182*e5436536SAndroid Build Coastguard Worker 
183*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(signal_size > 0);
184*e5436536SAndroid Build Coastguard Worker   for (i = signal_size; i != 0; i--) {
185*e5436536SAndroid Build Coastguard Worker     FIXP_DBL *pState = state + order - 1;
186*e5436536SAndroid Build Coastguard Worker     const FIXP_DBL *pCoeff = coeff + order - 1;
187*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp, accu;
188*e5436536SAndroid Build Coastguard Worker 
189*e5436536SAndroid Build Coastguard Worker     accu =
190*e5436536SAndroid Build Coastguard Worker         fMultSubDiv2(scaleValue(*pSignal, signal_e - 1), *pCoeff--, *pState--);
191*e5436536SAndroid Build Coastguard Worker     tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
192*e5436536SAndroid Build Coastguard Worker 
193*e5436536SAndroid Build Coastguard Worker     for (j = order - 1; j != 0; j--) {
194*e5436536SAndroid Build Coastguard Worker       accu = fMultSubDiv2(tmp >> 1, pCoeff[0], pState[0]);
195*e5436536SAndroid Build Coastguard Worker       tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
196*e5436536SAndroid Build Coastguard Worker 
197*e5436536SAndroid Build Coastguard Worker       accu = fMultAddDiv2(pState[0] >> 1, *pCoeff--, tmp);
198*e5436536SAndroid Build Coastguard Worker       pState[1] = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS);
199*e5436536SAndroid Build Coastguard Worker 
200*e5436536SAndroid Build Coastguard Worker       pState--;
201*e5436536SAndroid Build Coastguard Worker     }
202*e5436536SAndroid Build Coastguard Worker 
203*e5436536SAndroid Build Coastguard Worker     *pSignal = scaleValue(tmp, -signal_e_out);
204*e5436536SAndroid Build Coastguard Worker 
205*e5436536SAndroid Build Coastguard Worker     /* exponent of state[] is 0 */
206*e5436536SAndroid Build Coastguard Worker     pState[1] = tmp;
207*e5436536SAndroid Build Coastguard Worker     pSignal += inc;
208*e5436536SAndroid Build Coastguard Worker   }
209*e5436536SAndroid Build Coastguard Worker }
210*e5436536SAndroid Build Coastguard Worker 
211*e5436536SAndroid Build Coastguard Worker #endif
212*e5436536SAndroid Build Coastguard Worker 
213*e5436536SAndroid Build Coastguard Worker /* LPC_SYNTHESIS_IIR version */
CLpc_Synthesis(FIXP_DBL * signal,const int signal_size,const int signal_e,const int inc,const FIXP_LPC_TNS * lpcCoeff_m,const int lpcCoeff_e,const int order,FIXP_DBL * state,int * pStateIndex)214*e5436536SAndroid Build Coastguard Worker void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e,
215*e5436536SAndroid Build Coastguard Worker                     const int inc, const FIXP_LPC_TNS *lpcCoeff_m,
216*e5436536SAndroid Build Coastguard Worker                     const int lpcCoeff_e, const int order, FIXP_DBL *state,
217*e5436536SAndroid Build Coastguard Worker                     int *pStateIndex) {
218*e5436536SAndroid Build Coastguard Worker   int i, j;
219*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pSignal;
220*e5436536SAndroid Build Coastguard Worker   int stateIndex = *pStateIndex;
221*e5436536SAndroid Build Coastguard Worker 
222*e5436536SAndroid Build Coastguard Worker   FIXP_LPC_TNS coeff[2 * LPC_MAX_ORDER];
223*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS));
224*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS));
225*e5436536SAndroid Build Coastguard Worker 
226*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order <= LPC_MAX_ORDER);
227*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(stateIndex < order);
228*e5436536SAndroid Build Coastguard Worker 
229*e5436536SAndroid Build Coastguard Worker   if (inc == -1)
230*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[signal_size - 1];
231*e5436536SAndroid Build Coastguard Worker   else
232*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[0];
233*e5436536SAndroid Build Coastguard Worker 
234*e5436536SAndroid Build Coastguard Worker   /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */
235*e5436536SAndroid Build Coastguard Worker 
236*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < signal_size; i++) {
237*e5436536SAndroid Build Coastguard Worker     FIXP_DBL x;
238*e5436536SAndroid Build Coastguard Worker     const FIXP_LPC_TNS *pCoeff = coeff + order - stateIndex;
239*e5436536SAndroid Build Coastguard Worker 
240*e5436536SAndroid Build Coastguard Worker     x = scaleValue(*pSignal, -(lpcCoeff_e + 1));
241*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < order; j++) {
242*e5436536SAndroid Build Coastguard Worker       x -= fMultDiv2(state[j], pCoeff[j]);
243*e5436536SAndroid Build Coastguard Worker     }
244*e5436536SAndroid Build Coastguard Worker     x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS);
245*e5436536SAndroid Build Coastguard Worker 
246*e5436536SAndroid Build Coastguard Worker     /* Update states */
247*e5436536SAndroid Build Coastguard Worker     stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1);
248*e5436536SAndroid Build Coastguard Worker     state[stateIndex] = x;
249*e5436536SAndroid Build Coastguard Worker 
250*e5436536SAndroid Build Coastguard Worker     *pSignal = scaleValue(x, signal_e);
251*e5436536SAndroid Build Coastguard Worker     pSignal += inc;
252*e5436536SAndroid Build Coastguard Worker   }
253*e5436536SAndroid Build Coastguard Worker 
254*e5436536SAndroid Build Coastguard Worker   *pStateIndex = stateIndex;
255*e5436536SAndroid Build Coastguard Worker }
256*e5436536SAndroid Build Coastguard Worker /* default version */
CLpc_Synthesis(FIXP_DBL * signal,const int signal_size,const int signal_e,const int inc,const FIXP_LPC * lpcCoeff_m,const int lpcCoeff_e,const int order,FIXP_DBL * state,int * pStateIndex)257*e5436536SAndroid Build Coastguard Worker void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e,
258*e5436536SAndroid Build Coastguard Worker                     const int inc, const FIXP_LPC *lpcCoeff_m,
259*e5436536SAndroid Build Coastguard Worker                     const int lpcCoeff_e, const int order, FIXP_DBL *state,
260*e5436536SAndroid Build Coastguard Worker                     int *pStateIndex) {
261*e5436536SAndroid Build Coastguard Worker   int i, j;
262*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *pSignal;
263*e5436536SAndroid Build Coastguard Worker   int stateIndex = *pStateIndex;
264*e5436536SAndroid Build Coastguard Worker 
265*e5436536SAndroid Build Coastguard Worker   FIXP_LPC coeff[2 * LPC_MAX_ORDER];
266*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC));
267*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC));
268*e5436536SAndroid Build Coastguard Worker 
269*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(order <= LPC_MAX_ORDER);
270*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(stateIndex < order);
271*e5436536SAndroid Build Coastguard Worker 
272*e5436536SAndroid Build Coastguard Worker   if (inc == -1)
273*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[signal_size - 1];
274*e5436536SAndroid Build Coastguard Worker   else
275*e5436536SAndroid Build Coastguard Worker     pSignal = &signal[0];
276*e5436536SAndroid Build Coastguard Worker 
277*e5436536SAndroid Build Coastguard Worker   /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */
278*e5436536SAndroid Build Coastguard Worker 
279*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < signal_size; i++) {
280*e5436536SAndroid Build Coastguard Worker     FIXP_DBL x;
281*e5436536SAndroid Build Coastguard Worker     const FIXP_LPC *pCoeff = coeff + order - stateIndex;
282*e5436536SAndroid Build Coastguard Worker 
283*e5436536SAndroid Build Coastguard Worker     x = scaleValue(*pSignal, -(lpcCoeff_e + 1));
284*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < order; j++) {
285*e5436536SAndroid Build Coastguard Worker       x -= fMultDiv2(state[j], pCoeff[j]);
286*e5436536SAndroid Build Coastguard Worker     }
287*e5436536SAndroid Build Coastguard Worker     x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS);
288*e5436536SAndroid Build Coastguard Worker 
289*e5436536SAndroid Build Coastguard Worker     /* Update states */
290*e5436536SAndroid Build Coastguard Worker     stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1);
291*e5436536SAndroid Build Coastguard Worker     state[stateIndex] = x;
292*e5436536SAndroid Build Coastguard Worker 
293*e5436536SAndroid Build Coastguard Worker     *pSignal = scaleValue(x, signal_e);
294*e5436536SAndroid Build Coastguard Worker     pSignal += inc;
295*e5436536SAndroid Build Coastguard Worker   }
296*e5436536SAndroid Build Coastguard Worker 
297*e5436536SAndroid Build Coastguard Worker   *pStateIndex = stateIndex;
298*e5436536SAndroid Build Coastguard Worker }
299*e5436536SAndroid Build Coastguard Worker 
300*e5436536SAndroid Build Coastguard Worker /* FIR */
CLpc_Analysis(FIXP_DBL * RESTRICT signal,const int signal_size,const FIXP_LPC lpcCoeff_m[],const int lpcCoeff_e,const int order,FIXP_DBL * RESTRICT filtState,int * filtStateIndex)301*e5436536SAndroid Build Coastguard Worker void CLpc_Analysis(FIXP_DBL *RESTRICT signal, const int signal_size,
302*e5436536SAndroid Build Coastguard Worker                    const FIXP_LPC lpcCoeff_m[], const int lpcCoeff_e,
303*e5436536SAndroid Build Coastguard Worker                    const int order, FIXP_DBL *RESTRICT filtState,
304*e5436536SAndroid Build Coastguard Worker                    int *filtStateIndex) {
305*e5436536SAndroid Build Coastguard Worker   int stateIndex;
306*e5436536SAndroid Build Coastguard Worker   INT i, j, shift = lpcCoeff_e + 1; /* +1, because fMultDiv2 */
307*e5436536SAndroid Build Coastguard Worker   FIXP_DBL tmp;
308*e5436536SAndroid Build Coastguard Worker 
309*e5436536SAndroid Build Coastguard Worker   if (order <= 0) {
310*e5436536SAndroid Build Coastguard Worker     return;
311*e5436536SAndroid Build Coastguard Worker   }
312*e5436536SAndroid Build Coastguard Worker   if (filtStateIndex != NULL) {
313*e5436536SAndroid Build Coastguard Worker     stateIndex = *filtStateIndex;
314*e5436536SAndroid Build Coastguard Worker   } else {
315*e5436536SAndroid Build Coastguard Worker     stateIndex = 0;
316*e5436536SAndroid Build Coastguard Worker   }
317*e5436536SAndroid Build Coastguard Worker 
318*e5436536SAndroid Build Coastguard Worker   /* keep filter coefficients twice and save memory copy operation in
319*e5436536SAndroid Build Coastguard Worker      modulo state buffer */
320*e5436536SAndroid Build Coastguard Worker   FIXP_LPC coeff[2 * LPC_MAX_ORDER];
321*e5436536SAndroid Build Coastguard Worker   FIXP_LPC *pCoeff;
322*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC));
323*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC));
324*e5436536SAndroid Build Coastguard Worker 
325*e5436536SAndroid Build Coastguard Worker   /*
326*e5436536SAndroid Build Coastguard Worker       # Analysis filter, obtain residual.
327*e5436536SAndroid Build Coastguard Worker       for k = 0:BL-1
328*e5436536SAndroid Build Coastguard Worker               err(i-BL+k) = a * inputSignal(i-BL+k:-1:i-BL-M+k);
329*e5436536SAndroid Build Coastguard Worker       endfor
330*e5436536SAndroid Build Coastguard Worker    */
331*e5436536SAndroid Build Coastguard Worker 
332*e5436536SAndroid Build Coastguard Worker   FDK_ASSERT(shift >= 0);
333*e5436536SAndroid Build Coastguard Worker 
334*e5436536SAndroid Build Coastguard Worker   for (j = 0; j < signal_size; j++) {
335*e5436536SAndroid Build Coastguard Worker     pCoeff = &coeff[(order - stateIndex)];
336*e5436536SAndroid Build Coastguard Worker 
337*e5436536SAndroid Build Coastguard Worker     tmp = signal[j] >> shift;
338*e5436536SAndroid Build Coastguard Worker     for (i = 0; i < order; i++) {
339*e5436536SAndroid Build Coastguard Worker       tmp = fMultAddDiv2(tmp, pCoeff[i], filtState[i]);
340*e5436536SAndroid Build Coastguard Worker     }
341*e5436536SAndroid Build Coastguard Worker 
342*e5436536SAndroid Build Coastguard Worker     stateIndex =
343*e5436536SAndroid Build Coastguard Worker         ((stateIndex - 1) < 0) ? (stateIndex - 1 + order) : (stateIndex - 1);
344*e5436536SAndroid Build Coastguard Worker     filtState[stateIndex] = signal[j];
345*e5436536SAndroid Build Coastguard Worker 
346*e5436536SAndroid Build Coastguard Worker     signal[j] = tmp << shift;
347*e5436536SAndroid Build Coastguard Worker   }
348*e5436536SAndroid Build Coastguard Worker 
349*e5436536SAndroid Build Coastguard Worker   if (filtStateIndex != NULL) {
350*e5436536SAndroid Build Coastguard Worker     *filtStateIndex = stateIndex;
351*e5436536SAndroid Build Coastguard Worker   }
352*e5436536SAndroid Build Coastguard Worker }
353*e5436536SAndroid Build Coastguard Worker 
354*e5436536SAndroid Build Coastguard Worker /* For the LPC_SYNTHESIS_IIR version */
CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[],FIXP_LPC_TNS LpcCoeff[],INT numOfCoeff,FIXP_DBL workBuffer[])355*e5436536SAndroid Build Coastguard Worker INT CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[], FIXP_LPC_TNS LpcCoeff[],
356*e5436536SAndroid Build Coastguard Worker                      INT numOfCoeff, FIXP_DBL workBuffer[]) {
357*e5436536SAndroid Build Coastguard Worker   INT i, j;
358*e5436536SAndroid Build Coastguard Worker   INT shiftval,
359*e5436536SAndroid Build Coastguard Worker       par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */
360*e5436536SAndroid Build Coastguard Worker   FIXP_DBL maxVal = (FIXP_DBL)0;
361*e5436536SAndroid Build Coastguard Worker 
362*e5436536SAndroid Build Coastguard Worker   workBuffer[0] = FX_LPC_TNS2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal;
363*e5436536SAndroid Build Coastguard Worker   for (i = 1; i < numOfCoeff; i++) {
364*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < i / 2; j++) {
365*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp1, tmp2;
366*e5436536SAndroid Build Coastguard Worker 
367*e5436536SAndroid Build Coastguard Worker       tmp1 = workBuffer[j];
368*e5436536SAndroid Build Coastguard Worker       tmp2 = workBuffer[i - 1 - j];
369*e5436536SAndroid Build Coastguard Worker       workBuffer[j] += fMult(reflCoeff[i], tmp2);
370*e5436536SAndroid Build Coastguard Worker       workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1);
371*e5436536SAndroid Build Coastguard Worker     }
372*e5436536SAndroid Build Coastguard Worker     if (i & 1) {
373*e5436536SAndroid Build Coastguard Worker       workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]);
374*e5436536SAndroid Build Coastguard Worker     }
375*e5436536SAndroid Build Coastguard Worker 
376*e5436536SAndroid Build Coastguard Worker     workBuffer[i] = FX_LPC_TNS2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal;
377*e5436536SAndroid Build Coastguard Worker   }
378*e5436536SAndroid Build Coastguard Worker 
379*e5436536SAndroid Build Coastguard Worker   /* calculate exponent */
380*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numOfCoeff; i++) {
381*e5436536SAndroid Build Coastguard Worker     maxVal = fMax(maxVal, fAbs(workBuffer[i]));
382*e5436536SAndroid Build Coastguard Worker   }
383*e5436536SAndroid Build Coastguard Worker 
384*e5436536SAndroid Build Coastguard Worker   shiftval = fMin(fNorm(maxVal), par2LpcShiftVal);
385*e5436536SAndroid Build Coastguard Worker 
386*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numOfCoeff; i++) {
387*e5436536SAndroid Build Coastguard Worker     LpcCoeff[i] = FX_DBL2FX_LPC_TNS(workBuffer[i] << shiftval);
388*e5436536SAndroid Build Coastguard Worker   }
389*e5436536SAndroid Build Coastguard Worker 
390*e5436536SAndroid Build Coastguard Worker   return (par2LpcShiftVal - shiftval);
391*e5436536SAndroid Build Coastguard Worker }
392*e5436536SAndroid Build Coastguard Worker /* Default version */
CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[],FIXP_LPC LpcCoeff[],INT numOfCoeff,FIXP_DBL workBuffer[])393*e5436536SAndroid Build Coastguard Worker INT CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[], FIXP_LPC LpcCoeff[],
394*e5436536SAndroid Build Coastguard Worker                      INT numOfCoeff, FIXP_DBL workBuffer[]) {
395*e5436536SAndroid Build Coastguard Worker   INT i, j;
396*e5436536SAndroid Build Coastguard Worker   INT shiftval,
397*e5436536SAndroid Build Coastguard Worker       par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */
398*e5436536SAndroid Build Coastguard Worker   FIXP_DBL maxVal = (FIXP_DBL)0;
399*e5436536SAndroid Build Coastguard Worker 
400*e5436536SAndroid Build Coastguard Worker   workBuffer[0] = FX_LPC2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal;
401*e5436536SAndroid Build Coastguard Worker   for (i = 1; i < numOfCoeff; i++) {
402*e5436536SAndroid Build Coastguard Worker     for (j = 0; j < i / 2; j++) {
403*e5436536SAndroid Build Coastguard Worker       FIXP_DBL tmp1, tmp2;
404*e5436536SAndroid Build Coastguard Worker 
405*e5436536SAndroid Build Coastguard Worker       tmp1 = workBuffer[j];
406*e5436536SAndroid Build Coastguard Worker       tmp2 = workBuffer[i - 1 - j];
407*e5436536SAndroid Build Coastguard Worker       workBuffer[j] += fMult(reflCoeff[i], tmp2);
408*e5436536SAndroid Build Coastguard Worker       workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1);
409*e5436536SAndroid Build Coastguard Worker     }
410*e5436536SAndroid Build Coastguard Worker     if (i & 1) {
411*e5436536SAndroid Build Coastguard Worker       workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]);
412*e5436536SAndroid Build Coastguard Worker     }
413*e5436536SAndroid Build Coastguard Worker 
414*e5436536SAndroid Build Coastguard Worker     workBuffer[i] = FX_LPC2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal;
415*e5436536SAndroid Build Coastguard Worker   }
416*e5436536SAndroid Build Coastguard Worker 
417*e5436536SAndroid Build Coastguard Worker   /* calculate exponent */
418*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numOfCoeff; i++) {
419*e5436536SAndroid Build Coastguard Worker     maxVal = fMax(maxVal, fAbs(workBuffer[i]));
420*e5436536SAndroid Build Coastguard Worker   }
421*e5436536SAndroid Build Coastguard Worker 
422*e5436536SAndroid Build Coastguard Worker   shiftval = fMin(fNorm(maxVal), par2LpcShiftVal);
423*e5436536SAndroid Build Coastguard Worker 
424*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numOfCoeff; i++) {
425*e5436536SAndroid Build Coastguard Worker     LpcCoeff[i] = FX_DBL2FX_LPC(workBuffer[i] << shiftval);
426*e5436536SAndroid Build Coastguard Worker   }
427*e5436536SAndroid Build Coastguard Worker 
428*e5436536SAndroid Build Coastguard Worker   return (par2LpcShiftVal - shiftval);
429*e5436536SAndroid Build Coastguard Worker }
430*e5436536SAndroid Build Coastguard Worker 
CLpc_AutoToParcor(FIXP_DBL acorr[],const int acorr_e,FIXP_LPC reflCoeff[],const int numOfCoeff,FIXP_DBL * pPredictionGain_m,INT * pPredictionGain_e)431*e5436536SAndroid Build Coastguard Worker void CLpc_AutoToParcor(FIXP_DBL acorr[], const int acorr_e,
432*e5436536SAndroid Build Coastguard Worker                        FIXP_LPC reflCoeff[], const int numOfCoeff,
433*e5436536SAndroid Build Coastguard Worker                        FIXP_DBL *pPredictionGain_m, INT *pPredictionGain_e) {
434*e5436536SAndroid Build Coastguard Worker   INT i, j, scale = 0;
435*e5436536SAndroid Build Coastguard Worker   FIXP_DBL parcorWorkBuffer[LPC_MAX_ORDER];
436*e5436536SAndroid Build Coastguard Worker 
437*e5436536SAndroid Build Coastguard Worker   FIXP_DBL *workBuffer = parcorWorkBuffer;
438*e5436536SAndroid Build Coastguard Worker   FIXP_DBL autoCorr_0 = acorr[0];
439*e5436536SAndroid Build Coastguard Worker 
440*e5436536SAndroid Build Coastguard Worker   FDKmemclear(reflCoeff, numOfCoeff * sizeof(FIXP_LPC));
441*e5436536SAndroid Build Coastguard Worker 
442*e5436536SAndroid Build Coastguard Worker   if (autoCorr_0 == FL2FXCONST_DBL(0.0)) {
443*e5436536SAndroid Build Coastguard Worker     if (pPredictionGain_m != NULL) {
444*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_m = FL2FXCONST_DBL(0.5f);
445*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_e = 1;
446*e5436536SAndroid Build Coastguard Worker     }
447*e5436536SAndroid Build Coastguard Worker     return;
448*e5436536SAndroid Build Coastguard Worker   }
449*e5436536SAndroid Build Coastguard Worker 
450*e5436536SAndroid Build Coastguard Worker   FDKmemcpy(workBuffer, acorr + 1, numOfCoeff * sizeof(FIXP_DBL));
451*e5436536SAndroid Build Coastguard Worker   for (i = 0; i < numOfCoeff; i++) {
452*e5436536SAndroid Build Coastguard Worker     LONG sign = ((LONG)workBuffer[0] >> (DFRACT_BITS - 1));
453*e5436536SAndroid Build Coastguard Worker     FIXP_DBL tmp = (FIXP_DBL)((LONG)workBuffer[0] ^ sign);
454*e5436536SAndroid Build Coastguard Worker 
455*e5436536SAndroid Build Coastguard Worker     /* Check preconditions for division function: num<=denum             */
456*e5436536SAndroid Build Coastguard Worker     /* For 1st iteration acorr[0] cannot be 0, it is checked before loop */
457*e5436536SAndroid Build Coastguard Worker     /* Due to exor operation with "sign", num(=tmp) is greater/equal 0   */
458*e5436536SAndroid Build Coastguard Worker     if (acorr[0] < tmp) break;
459*e5436536SAndroid Build Coastguard Worker 
460*e5436536SAndroid Build Coastguard Worker     /* tmp = div(num, denum, 16) */
461*e5436536SAndroid Build Coastguard Worker     tmp = (FIXP_DBL)((LONG)schur_div(tmp, acorr[0], FRACT_BITS) ^ (~sign));
462*e5436536SAndroid Build Coastguard Worker 
463*e5436536SAndroid Build Coastguard Worker     reflCoeff[i] = FX_DBL2FX_LPC(tmp);
464*e5436536SAndroid Build Coastguard Worker 
465*e5436536SAndroid Build Coastguard Worker     for (j = numOfCoeff - i - 1; j >= 0; j--) {
466*e5436536SAndroid Build Coastguard Worker       FIXP_DBL accu1 = fMult(tmp, acorr[j]);
467*e5436536SAndroid Build Coastguard Worker       FIXP_DBL accu2 = fMult(tmp, workBuffer[j]);
468*e5436536SAndroid Build Coastguard Worker       workBuffer[j] += accu1;
469*e5436536SAndroid Build Coastguard Worker       acorr[j] += accu2;
470*e5436536SAndroid Build Coastguard Worker     }
471*e5436536SAndroid Build Coastguard Worker     /* Check preconditions for division function: denum (=acorr[0]) > 0 */
472*e5436536SAndroid Build Coastguard Worker     if (acorr[0] == (FIXP_DBL)0) break;
473*e5436536SAndroid Build Coastguard Worker 
474*e5436536SAndroid Build Coastguard Worker     workBuffer++;
475*e5436536SAndroid Build Coastguard Worker   }
476*e5436536SAndroid Build Coastguard Worker 
477*e5436536SAndroid Build Coastguard Worker   if (pPredictionGain_m != NULL) {
478*e5436536SAndroid Build Coastguard Worker     if (acorr[0] > (FIXP_DBL)0) {
479*e5436536SAndroid Build Coastguard Worker       /* prediction gain = signal power / error (residual) power */
480*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_m = fDivNormSigned(autoCorr_0, acorr[0], &scale);
481*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_e = scale;
482*e5436536SAndroid Build Coastguard Worker     } else {
483*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_m = (FIXP_DBL)0;
484*e5436536SAndroid Build Coastguard Worker       *pPredictionGain_e = 0;
485*e5436536SAndroid Build Coastguard Worker     }
486*e5436536SAndroid Build Coastguard Worker   }
487*e5436536SAndroid Build Coastguard Worker }
488