1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /******************* Library for basic calculation routines ********************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s):
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description:
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker /*!
104*e5436536SAndroid Build Coastguard Worker \file dct.cpp
105*e5436536SAndroid Build Coastguard Worker \brief DCT Implementations
106*e5436536SAndroid Build Coastguard Worker Library functions to calculate standard DCTs. This will most likely be
107*e5436536SAndroid Build Coastguard Worker replaced by hand-optimized functions for the specific target processor.
108*e5436536SAndroid Build Coastguard Worker
109*e5436536SAndroid Build Coastguard Worker Three different implementations of the dct type II and the dct type III
110*e5436536SAndroid Build Coastguard Worker transforms are provided.
111*e5436536SAndroid Build Coastguard Worker
112*e5436536SAndroid Build Coastguard Worker By default implementations which are based on a single, standard complex
113*e5436536SAndroid Build Coastguard Worker FFT-kernel are used (dctII_f() and dctIII_f()). These are specifically helpful
114*e5436536SAndroid Build Coastguard Worker in cases where optimized FFT libraries are already available. The FFT used in
115*e5436536SAndroid Build Coastguard Worker these implementation is FFT rad2 from FDK_tools.
116*e5436536SAndroid Build Coastguard Worker
117*e5436536SAndroid Build Coastguard Worker Of course, one might also use DCT-libraries should they be available. The DCT
118*e5436536SAndroid Build Coastguard Worker and DST type IV implementations are only available in a version based on a
119*e5436536SAndroid Build Coastguard Worker complex FFT kernel.
120*e5436536SAndroid Build Coastguard Worker */
121*e5436536SAndroid Build Coastguard Worker
122*e5436536SAndroid Build Coastguard Worker #include "dct.h"
123*e5436536SAndroid Build Coastguard Worker
124*e5436536SAndroid Build Coastguard Worker #include "FDK_tools_rom.h"
125*e5436536SAndroid Build Coastguard Worker #include "fft.h"
126*e5436536SAndroid Build Coastguard Worker
dct_getTables(const FIXP_WTP ** ptwiddle,const FIXP_STP ** sin_twiddle,int * sin_step,int length)127*e5436536SAndroid Build Coastguard Worker void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle,
128*e5436536SAndroid Build Coastguard Worker int *sin_step, int length) {
129*e5436536SAndroid Build Coastguard Worker const FIXP_WTP *twiddle;
130*e5436536SAndroid Build Coastguard Worker int ld2_length;
131*e5436536SAndroid Build Coastguard Worker
132*e5436536SAndroid Build Coastguard Worker /* Get ld2 of length - 2 + 1
133*e5436536SAndroid Build Coastguard Worker -2: because first table entry is window of size 4
134*e5436536SAndroid Build Coastguard Worker +1: because we already include +1 because of ceil(log2(length)) */
135*e5436536SAndroid Build Coastguard Worker ld2_length = DFRACT_BITS - 1 - fNormz((FIXP_DBL)length) - 1;
136*e5436536SAndroid Build Coastguard Worker
137*e5436536SAndroid Build Coastguard Worker /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */
138*e5436536SAndroid Build Coastguard Worker switch ((length) >> (ld2_length - 1)) {
139*e5436536SAndroid Build Coastguard Worker case 0x4: /* radix 2 */
140*e5436536SAndroid Build Coastguard Worker *sin_twiddle = SineTable1024;
141*e5436536SAndroid Build Coastguard Worker *sin_step = 1 << (10 - ld2_length);
142*e5436536SAndroid Build Coastguard Worker twiddle = windowSlopes[0][0][ld2_length - 1];
143*e5436536SAndroid Build Coastguard Worker break;
144*e5436536SAndroid Build Coastguard Worker case 0x7: /* 10 ms */
145*e5436536SAndroid Build Coastguard Worker *sin_twiddle = SineTable480;
146*e5436536SAndroid Build Coastguard Worker *sin_step = 1 << (8 - ld2_length);
147*e5436536SAndroid Build Coastguard Worker twiddle = windowSlopes[0][1][ld2_length];
148*e5436536SAndroid Build Coastguard Worker break;
149*e5436536SAndroid Build Coastguard Worker case 0x6: /* 3/4 of radix 2 */
150*e5436536SAndroid Build Coastguard Worker *sin_twiddle = SineTable384;
151*e5436536SAndroid Build Coastguard Worker *sin_step = 1 << (8 - ld2_length);
152*e5436536SAndroid Build Coastguard Worker twiddle = windowSlopes[0][2][ld2_length];
153*e5436536SAndroid Build Coastguard Worker break;
154*e5436536SAndroid Build Coastguard Worker case 0x5: /* 5/16 of radix 2*/
155*e5436536SAndroid Build Coastguard Worker *sin_twiddle = SineTable80;
156*e5436536SAndroid Build Coastguard Worker *sin_step = 1 << (6 - ld2_length);
157*e5436536SAndroid Build Coastguard Worker twiddle = windowSlopes[0][3][ld2_length];
158*e5436536SAndroid Build Coastguard Worker break;
159*e5436536SAndroid Build Coastguard Worker default:
160*e5436536SAndroid Build Coastguard Worker *sin_twiddle = NULL;
161*e5436536SAndroid Build Coastguard Worker *sin_step = 0;
162*e5436536SAndroid Build Coastguard Worker twiddle = NULL;
163*e5436536SAndroid Build Coastguard Worker break;
164*e5436536SAndroid Build Coastguard Worker }
165*e5436536SAndroid Build Coastguard Worker
166*e5436536SAndroid Build Coastguard Worker if (ptwiddle != NULL) {
167*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(twiddle != NULL);
168*e5436536SAndroid Build Coastguard Worker *ptwiddle = twiddle;
169*e5436536SAndroid Build Coastguard Worker }
170*e5436536SAndroid Build Coastguard Worker
171*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(*sin_step > 0);
172*e5436536SAndroid Build Coastguard Worker }
173*e5436536SAndroid Build Coastguard Worker
174*e5436536SAndroid Build Coastguard Worker #if !defined(FUNCTION_dct_III)
dct_III(FIXP_DBL * pDat,FIXP_DBL * tmp,int L,int * pDat_e)175*e5436536SAndroid Build Coastguard Worker void dct_III(FIXP_DBL *pDat, /*!< pointer to input/output */
176*e5436536SAndroid Build Coastguard Worker FIXP_DBL *tmp, /*!< pointer to temporal working buffer */
177*e5436536SAndroid Build Coastguard Worker int L, /*!< lenght of transform */
178*e5436536SAndroid Build Coastguard Worker int *pDat_e) {
179*e5436536SAndroid Build Coastguard Worker const FIXP_WTP *sin_twiddle;
180*e5436536SAndroid Build Coastguard Worker int i;
181*e5436536SAndroid Build Coastguard Worker FIXP_DBL xr, accu1, accu2;
182*e5436536SAndroid Build Coastguard Worker int inc, index;
183*e5436536SAndroid Build Coastguard Worker int M = L >> 1;
184*e5436536SAndroid Build Coastguard Worker
185*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L % 4 == 0);
186*e5436536SAndroid Build Coastguard Worker dct_getTables(NULL, &sin_twiddle, &inc, L);
187*e5436536SAndroid Build Coastguard Worker inc >>= 1;
188*e5436536SAndroid Build Coastguard Worker
189*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pTmp_0 = &tmp[2];
190*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pTmp_1 = &tmp[(M - 1) * 2];
191*e5436536SAndroid Build Coastguard Worker
192*e5436536SAndroid Build Coastguard Worker index = 4 * inc;
193*e5436536SAndroid Build Coastguard Worker
194*e5436536SAndroid Build Coastguard Worker /* This loop performs multiplication for index i (i*inc) */
195*e5436536SAndroid Build Coastguard Worker for (i = 1; i<M>> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) {
196*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu3, accu4, accu5, accu6;
197*e5436536SAndroid Build Coastguard Worker
198*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu2, &accu1, pDat[L - i], pDat[i], sin_twiddle[i * inc]);
199*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu4, &accu3, pDat[M + i], pDat[M - i],
200*e5436536SAndroid Build Coastguard Worker sin_twiddle[(M - i) * inc]);
201*e5436536SAndroid Build Coastguard Worker accu3 >>= 1;
202*e5436536SAndroid Build Coastguard Worker accu4 >>= 1;
203*e5436536SAndroid Build Coastguard Worker
204*e5436536SAndroid Build Coastguard Worker /* This method is better for ARM926, that uses operand2 shifted right by 1
205*e5436536SAndroid Build Coastguard Worker * always */
206*e5436536SAndroid Build Coastguard Worker if (2 * i < (M / 2)) {
207*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu6, &accu5, (accu3 - (accu1 >> 1)),
208*e5436536SAndroid Build Coastguard Worker ((accu2 >> 1) + accu4), sin_twiddle[index]);
209*e5436536SAndroid Build Coastguard Worker } else {
210*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu6, &accu5, ((accu2 >> 1) + accu4),
211*e5436536SAndroid Build Coastguard Worker (accu3 - (accu1 >> 1)), sin_twiddle[index]);
212*e5436536SAndroid Build Coastguard Worker accu6 = -accu6;
213*e5436536SAndroid Build Coastguard Worker }
214*e5436536SAndroid Build Coastguard Worker xr = (accu1 >> 1) + accu3;
215*e5436536SAndroid Build Coastguard Worker pTmp_0[0] = (xr >> 1) - accu5;
216*e5436536SAndroid Build Coastguard Worker pTmp_1[0] = (xr >> 1) + accu5;
217*e5436536SAndroid Build Coastguard Worker
218*e5436536SAndroid Build Coastguard Worker xr = (accu2 >> 1) - accu4;
219*e5436536SAndroid Build Coastguard Worker pTmp_0[1] = (xr >> 1) - accu6;
220*e5436536SAndroid Build Coastguard Worker pTmp_1[1] = -((xr >> 1) + accu6);
221*e5436536SAndroid Build Coastguard Worker
222*e5436536SAndroid Build Coastguard Worker /* Create index helper variables for (4*i)*inc indexed equivalent values of
223*e5436536SAndroid Build Coastguard Worker * short tables. */
224*e5436536SAndroid Build Coastguard Worker if (2 * i < ((M / 2) - 1)) {
225*e5436536SAndroid Build Coastguard Worker index += 4 * inc;
226*e5436536SAndroid Build Coastguard Worker } else if (2 * i >= ((M / 2))) {
227*e5436536SAndroid Build Coastguard Worker index -= 4 * inc;
228*e5436536SAndroid Build Coastguard Worker }
229*e5436536SAndroid Build Coastguard Worker }
230*e5436536SAndroid Build Coastguard Worker
231*e5436536SAndroid Build Coastguard Worker xr = fMultDiv2(pDat[M], sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */
232*e5436536SAndroid Build Coastguard Worker tmp[0] = ((pDat[0] >> 1) + xr) >> 1;
233*e5436536SAndroid Build Coastguard Worker tmp[1] = ((pDat[0] >> 1) - xr) >> 1;
234*e5436536SAndroid Build Coastguard Worker
235*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu2, &accu1, pDat[L - (M / 2)], pDat[M / 2],
236*e5436536SAndroid Build Coastguard Worker sin_twiddle[M * inc / 2]);
237*e5436536SAndroid Build Coastguard Worker tmp[M] = accu1 >> 1;
238*e5436536SAndroid Build Coastguard Worker tmp[M + 1] = accu2 >> 1;
239*e5436536SAndroid Build Coastguard Worker
240*e5436536SAndroid Build Coastguard Worker /* dit_fft expects 1 bit scaled input values */
241*e5436536SAndroid Build Coastguard Worker fft(M, tmp, pDat_e);
242*e5436536SAndroid Build Coastguard Worker
243*e5436536SAndroid Build Coastguard Worker /* ARM926: 12 cycles per 2-iteration, no overhead code by compiler */
244*e5436536SAndroid Build Coastguard Worker pTmp_1 = &tmp[L];
245*e5436536SAndroid Build Coastguard Worker for (i = M >> 1; i--;) {
246*e5436536SAndroid Build Coastguard Worker FIXP_DBL tmp1, tmp2, tmp3, tmp4;
247*e5436536SAndroid Build Coastguard Worker tmp1 = *tmp++;
248*e5436536SAndroid Build Coastguard Worker tmp2 = *tmp++;
249*e5436536SAndroid Build Coastguard Worker tmp3 = *--pTmp_1;
250*e5436536SAndroid Build Coastguard Worker tmp4 = *--pTmp_1;
251*e5436536SAndroid Build Coastguard Worker *pDat++ = tmp1;
252*e5436536SAndroid Build Coastguard Worker *pDat++ = tmp3;
253*e5436536SAndroid Build Coastguard Worker *pDat++ = tmp2;
254*e5436536SAndroid Build Coastguard Worker *pDat++ = tmp4;
255*e5436536SAndroid Build Coastguard Worker }
256*e5436536SAndroid Build Coastguard Worker
257*e5436536SAndroid Build Coastguard Worker *pDat_e += 2;
258*e5436536SAndroid Build Coastguard Worker }
259*e5436536SAndroid Build Coastguard Worker
dst_III(FIXP_DBL * pDat,FIXP_DBL * tmp,int L,int * pDat_e)260*e5436536SAndroid Build Coastguard Worker void dst_III(FIXP_DBL *pDat, /*!< pointer to input/output */
261*e5436536SAndroid Build Coastguard Worker FIXP_DBL *tmp, /*!< pointer to temporal working buffer */
262*e5436536SAndroid Build Coastguard Worker int L, /*!< lenght of transform */
263*e5436536SAndroid Build Coastguard Worker int *pDat_e) {
264*e5436536SAndroid Build Coastguard Worker int L2 = L >> 1;
265*e5436536SAndroid Build Coastguard Worker int i;
266*e5436536SAndroid Build Coastguard Worker FIXP_DBL t;
267*e5436536SAndroid Build Coastguard Worker
268*e5436536SAndroid Build Coastguard Worker /* note: DCT III is reused here, direct DST III implementation might be more
269*e5436536SAndroid Build Coastguard Worker * efficient */
270*e5436536SAndroid Build Coastguard Worker
271*e5436536SAndroid Build Coastguard Worker /* mirror input */
272*e5436536SAndroid Build Coastguard Worker for (i = 0; i < L2; i++) {
273*e5436536SAndroid Build Coastguard Worker t = pDat[i];
274*e5436536SAndroid Build Coastguard Worker pDat[i] = pDat[L - 1 - i];
275*e5436536SAndroid Build Coastguard Worker pDat[L - 1 - i] = t;
276*e5436536SAndroid Build Coastguard Worker }
277*e5436536SAndroid Build Coastguard Worker
278*e5436536SAndroid Build Coastguard Worker /* DCT-III */
279*e5436536SAndroid Build Coastguard Worker dct_III(pDat, tmp, L, pDat_e);
280*e5436536SAndroid Build Coastguard Worker
281*e5436536SAndroid Build Coastguard Worker /* flip signs at odd indices */
282*e5436536SAndroid Build Coastguard Worker for (i = 1; i < L; i += 2) pDat[i] = -pDat[i];
283*e5436536SAndroid Build Coastguard Worker }
284*e5436536SAndroid Build Coastguard Worker
285*e5436536SAndroid Build Coastguard Worker #endif
286*e5436536SAndroid Build Coastguard Worker
287*e5436536SAndroid Build Coastguard Worker #if !defined(FUNCTION_dct_II)
dct_II(FIXP_DBL * pDat,FIXP_DBL * tmp,int L,int * pDat_e)288*e5436536SAndroid Build Coastguard Worker void dct_II(
289*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pDat, /*!< pointer to input/output */
290*e5436536SAndroid Build Coastguard Worker FIXP_DBL *tmp, /*!< pointer to temporal working buffer */
291*e5436536SAndroid Build Coastguard Worker int L, /*!< lenght of transform (has to be a multiple of 8 (or 4 in case
292*e5436536SAndroid Build Coastguard Worker DCT_II_L_MULTIPLE_OF_4_SUPPORT is defined) */
293*e5436536SAndroid Build Coastguard Worker int *pDat_e) {
294*e5436536SAndroid Build Coastguard Worker const FIXP_WTP *sin_twiddle;
295*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2;
296*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pTmp_0, *pTmp_1;
297*e5436536SAndroid Build Coastguard Worker
298*e5436536SAndroid Build Coastguard Worker int i;
299*e5436536SAndroid Build Coastguard Worker int inc, index = 0;
300*e5436536SAndroid Build Coastguard Worker int M = L >> 1;
301*e5436536SAndroid Build Coastguard Worker
302*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L % 4 == 0);
303*e5436536SAndroid Build Coastguard Worker dct_getTables(NULL, &sin_twiddle, &inc, L);
304*e5436536SAndroid Build Coastguard Worker inc >>= 1;
305*e5436536SAndroid Build Coastguard Worker
306*e5436536SAndroid Build Coastguard Worker {
307*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M; i++) {
308*e5436536SAndroid Build Coastguard Worker tmp[i] = pDat[2 * i] >> 2;
309*e5436536SAndroid Build Coastguard Worker tmp[L - 1 - i] = pDat[2 * i + 1] >> 2;
310*e5436536SAndroid Build Coastguard Worker }
311*e5436536SAndroid Build Coastguard Worker }
312*e5436536SAndroid Build Coastguard Worker
313*e5436536SAndroid Build Coastguard Worker fft(M, tmp, pDat_e);
314*e5436536SAndroid Build Coastguard Worker
315*e5436536SAndroid Build Coastguard Worker pTmp_0 = &tmp[2];
316*e5436536SAndroid Build Coastguard Worker pTmp_1 = &tmp[(M - 1) * 2];
317*e5436536SAndroid Build Coastguard Worker
318*e5436536SAndroid Build Coastguard Worker index = inc * 4;
319*e5436536SAndroid Build Coastguard Worker
320*e5436536SAndroid Build Coastguard Worker for (i = 1; i<M>> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) {
321*e5436536SAndroid Build Coastguard Worker FIXP_DBL a1, a2;
322*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu3, accu4;
323*e5436536SAndroid Build Coastguard Worker
324*e5436536SAndroid Build Coastguard Worker a1 = ((pTmp_0[1] >> 1) + (pTmp_1[1] >> 1));
325*e5436536SAndroid Build Coastguard Worker a2 = ((pTmp_1[0] >> 1) - (pTmp_0[0] >> 1));
326*e5436536SAndroid Build Coastguard Worker
327*e5436536SAndroid Build Coastguard Worker if (2 * i < (M / 2)) {
328*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, a2, a1, sin_twiddle[index]);
329*e5436536SAndroid Build Coastguard Worker } else {
330*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, a1, a2, sin_twiddle[index]);
331*e5436536SAndroid Build Coastguard Worker accu1 = -accu1;
332*e5436536SAndroid Build Coastguard Worker }
333*e5436536SAndroid Build Coastguard Worker accu1 <<= 1;
334*e5436536SAndroid Build Coastguard Worker accu2 <<= 1;
335*e5436536SAndroid Build Coastguard Worker
336*e5436536SAndroid Build Coastguard Worker a1 = ((pTmp_0[0] >> 1) + (pTmp_1[0] >> 1));
337*e5436536SAndroid Build Coastguard Worker a2 = ((pTmp_0[1] >> 1) - (pTmp_1[1] >> 1));
338*e5436536SAndroid Build Coastguard Worker
339*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, (accu1 + a2), (a1 + accu2), sin_twiddle[i * inc]);
340*e5436536SAndroid Build Coastguard Worker pDat[L - i] = -accu3;
341*e5436536SAndroid Build Coastguard Worker pDat[i] = accu4;
342*e5436536SAndroid Build Coastguard Worker
343*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, (accu1 - a2), (a1 - accu2),
344*e5436536SAndroid Build Coastguard Worker sin_twiddle[(M - i) * inc]);
345*e5436536SAndroid Build Coastguard Worker pDat[M + i] = -accu3;
346*e5436536SAndroid Build Coastguard Worker pDat[M - i] = accu4;
347*e5436536SAndroid Build Coastguard Worker
348*e5436536SAndroid Build Coastguard Worker /* Create index helper variables for (4*i)*inc indexed equivalent values of
349*e5436536SAndroid Build Coastguard Worker * short tables. */
350*e5436536SAndroid Build Coastguard Worker if (2 * i < ((M / 2) - 1)) {
351*e5436536SAndroid Build Coastguard Worker index += 4 * inc;
352*e5436536SAndroid Build Coastguard Worker } else if (2 * i >= ((M / 2))) {
353*e5436536SAndroid Build Coastguard Worker index -= 4 * inc;
354*e5436536SAndroid Build Coastguard Worker }
355*e5436536SAndroid Build Coastguard Worker }
356*e5436536SAndroid Build Coastguard Worker
357*e5436536SAndroid Build Coastguard Worker cplxMult(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]);
358*e5436536SAndroid Build Coastguard Worker pDat[L - (M / 2)] = accu2;
359*e5436536SAndroid Build Coastguard Worker pDat[M / 2] = accu1;
360*e5436536SAndroid Build Coastguard Worker
361*e5436536SAndroid Build Coastguard Worker pDat[0] = tmp[0] + tmp[1];
362*e5436536SAndroid Build Coastguard Worker pDat[M] = fMult(tmp[0] - tmp[1],
363*e5436536SAndroid Build Coastguard Worker sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */
364*e5436536SAndroid Build Coastguard Worker
365*e5436536SAndroid Build Coastguard Worker *pDat_e += 2;
366*e5436536SAndroid Build Coastguard Worker }
367*e5436536SAndroid Build Coastguard Worker #endif
368*e5436536SAndroid Build Coastguard Worker
369*e5436536SAndroid Build Coastguard Worker #if !defined(FUNCTION_dct_IV)
370*e5436536SAndroid Build Coastguard Worker
dct_IV(FIXP_DBL * pDat,int L,int * pDat_e)371*e5436536SAndroid Build Coastguard Worker void dct_IV(FIXP_DBL *pDat, int L, int *pDat_e) {
372*e5436536SAndroid Build Coastguard Worker int sin_step = 0;
373*e5436536SAndroid Build Coastguard Worker int M = L >> 1;
374*e5436536SAndroid Build Coastguard Worker
375*e5436536SAndroid Build Coastguard Worker const FIXP_WTP *twiddle;
376*e5436536SAndroid Build Coastguard Worker const FIXP_STP *sin_twiddle;
377*e5436536SAndroid Build Coastguard Worker
378*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L >= 4);
379*e5436536SAndroid Build Coastguard Worker
380*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L >= 4);
381*e5436536SAndroid Build Coastguard Worker
382*e5436536SAndroid Build Coastguard Worker dct_getTables(&twiddle, &sin_twiddle, &sin_step, L);
383*e5436536SAndroid Build Coastguard Worker
384*e5436536SAndroid Build Coastguard Worker {
385*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
386*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
387*e5436536SAndroid Build Coastguard Worker int i;
388*e5436536SAndroid Build Coastguard Worker
389*e5436536SAndroid Build Coastguard Worker /* 29 cycles on ARM926 */
390*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) {
391*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2, accu3, accu4;
392*e5436536SAndroid Build Coastguard Worker
393*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[1];
394*e5436536SAndroid Build Coastguard Worker accu2 = pDat_0[0];
395*e5436536SAndroid Build Coastguard Worker accu3 = pDat_0[1];
396*e5436536SAndroid Build Coastguard Worker accu4 = pDat_1[0];
397*e5436536SAndroid Build Coastguard Worker
398*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
399*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]);
400*e5436536SAndroid Build Coastguard Worker
401*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu2 >> 1;
402*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu1 >> 1;
403*e5436536SAndroid Build Coastguard Worker pDat_1[0] = accu4 >> 1;
404*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -(accu3 >> 1);
405*e5436536SAndroid Build Coastguard Worker }
406*e5436536SAndroid Build Coastguard Worker if (M & 1) {
407*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2;
408*e5436536SAndroid Build Coastguard Worker
409*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[1];
410*e5436536SAndroid Build Coastguard Worker accu2 = pDat_0[0];
411*e5436536SAndroid Build Coastguard Worker
412*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
413*e5436536SAndroid Build Coastguard Worker
414*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu2 >> 1;
415*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu1 >> 1;
416*e5436536SAndroid Build Coastguard Worker }
417*e5436536SAndroid Build Coastguard Worker }
418*e5436536SAndroid Build Coastguard Worker
419*e5436536SAndroid Build Coastguard Worker fft(M, pDat, pDat_e);
420*e5436536SAndroid Build Coastguard Worker
421*e5436536SAndroid Build Coastguard Worker {
422*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
423*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
424*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2, accu3, accu4;
425*e5436536SAndroid Build Coastguard Worker int idx, i;
426*e5436536SAndroid Build Coastguard Worker
427*e5436536SAndroid Build Coastguard Worker /* Sin and Cos values are 0.0f and 1.0f */
428*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[0];
429*e5436536SAndroid Build Coastguard Worker accu2 = pDat_1[1];
430*e5436536SAndroid Build Coastguard Worker
431*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -pDat_0[1];
432*e5436536SAndroid Build Coastguard Worker
433*e5436536SAndroid Build Coastguard Worker /* 28 cycles for ARM926 */
434*e5436536SAndroid Build Coastguard Worker for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) {
435*e5436536SAndroid Build Coastguard Worker FIXP_STP twd = sin_twiddle[idx];
436*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, accu1, accu2, twd);
437*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu3;
438*e5436536SAndroid Build Coastguard Worker pDat_1[0] = accu4;
439*e5436536SAndroid Build Coastguard Worker
440*e5436536SAndroid Build Coastguard Worker pDat_0 += 2;
441*e5436536SAndroid Build Coastguard Worker pDat_1 -= 2;
442*e5436536SAndroid Build Coastguard Worker
443*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
444*e5436536SAndroid Build Coastguard Worker
445*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[0];
446*e5436536SAndroid Build Coastguard Worker accu2 = pDat_1[1];
447*e5436536SAndroid Build Coastguard Worker
448*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -accu3;
449*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu4;
450*e5436536SAndroid Build Coastguard Worker }
451*e5436536SAndroid Build Coastguard Worker
452*e5436536SAndroid Build Coastguard Worker if ((M & 1) == 0) {
453*e5436536SAndroid Build Coastguard Worker /* Last Sin and Cos value pair are the same */
454*e5436536SAndroid Build Coastguard Worker accu1 = fMult(accu1, WTC(0x5a82799a));
455*e5436536SAndroid Build Coastguard Worker accu2 = fMult(accu2, WTC(0x5a82799a));
456*e5436536SAndroid Build Coastguard Worker
457*e5436536SAndroid Build Coastguard Worker pDat_1[0] = accu1 + accu2;
458*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu1 - accu2;
459*e5436536SAndroid Build Coastguard Worker }
460*e5436536SAndroid Build Coastguard Worker }
461*e5436536SAndroid Build Coastguard Worker
462*e5436536SAndroid Build Coastguard Worker /* Add twiddeling scale. */
463*e5436536SAndroid Build Coastguard Worker *pDat_e += 2;
464*e5436536SAndroid Build Coastguard Worker }
465*e5436536SAndroid Build Coastguard Worker #endif /* defined (FUNCTION_dct_IV) */
466*e5436536SAndroid Build Coastguard Worker
467*e5436536SAndroid Build Coastguard Worker #if !defined(FUNCTION_dst_IV)
dst_IV(FIXP_DBL * pDat,int L,int * pDat_e)468*e5436536SAndroid Build Coastguard Worker void dst_IV(FIXP_DBL *pDat, int L, int *pDat_e) {
469*e5436536SAndroid Build Coastguard Worker int sin_step = 0;
470*e5436536SAndroid Build Coastguard Worker int M = L >> 1;
471*e5436536SAndroid Build Coastguard Worker
472*e5436536SAndroid Build Coastguard Worker const FIXP_WTP *twiddle;
473*e5436536SAndroid Build Coastguard Worker const FIXP_STP *sin_twiddle;
474*e5436536SAndroid Build Coastguard Worker
475*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L >= 4);
476*e5436536SAndroid Build Coastguard Worker
477*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(L >= 4);
478*e5436536SAndroid Build Coastguard Worker
479*e5436536SAndroid Build Coastguard Worker dct_getTables(&twiddle, &sin_twiddle, &sin_step, L);
480*e5436536SAndroid Build Coastguard Worker
481*e5436536SAndroid Build Coastguard Worker {
482*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_0 = &pDat[0];
483*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2];
484*e5436536SAndroid Build Coastguard Worker int i;
485*e5436536SAndroid Build Coastguard Worker
486*e5436536SAndroid Build Coastguard Worker /* 34 cycles on ARM926 */
487*e5436536SAndroid Build Coastguard Worker for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) {
488*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2, accu3, accu4;
489*e5436536SAndroid Build Coastguard Worker
490*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[1] >> 1;
491*e5436536SAndroid Build Coastguard Worker accu2 = -(pDat_0[0] >> 1);
492*e5436536SAndroid Build Coastguard Worker accu3 = pDat_0[1] >> 1;
493*e5436536SAndroid Build Coastguard Worker accu4 = -(pDat_1[0] >> 1);
494*e5436536SAndroid Build Coastguard Worker
495*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
496*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]);
497*e5436536SAndroid Build Coastguard Worker
498*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu2;
499*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu1;
500*e5436536SAndroid Build Coastguard Worker pDat_1[0] = accu4;
501*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -accu3;
502*e5436536SAndroid Build Coastguard Worker }
503*e5436536SAndroid Build Coastguard Worker if (M & 1) {
504*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2;
505*e5436536SAndroid Build Coastguard Worker
506*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[1];
507*e5436536SAndroid Build Coastguard Worker accu2 = -pDat_0[0];
508*e5436536SAndroid Build Coastguard Worker
509*e5436536SAndroid Build Coastguard Worker cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
510*e5436536SAndroid Build Coastguard Worker
511*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu2 >> 1;
512*e5436536SAndroid Build Coastguard Worker pDat_0[1] = accu1 >> 1;
513*e5436536SAndroid Build Coastguard Worker }
514*e5436536SAndroid Build Coastguard Worker }
515*e5436536SAndroid Build Coastguard Worker
516*e5436536SAndroid Build Coastguard Worker fft(M, pDat, pDat_e);
517*e5436536SAndroid Build Coastguard Worker
518*e5436536SAndroid Build Coastguard Worker {
519*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_0;
520*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pDat_1;
521*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu1, accu2, accu3, accu4;
522*e5436536SAndroid Build Coastguard Worker int idx, i;
523*e5436536SAndroid Build Coastguard Worker
524*e5436536SAndroid Build Coastguard Worker pDat_0 = &pDat[0];
525*e5436536SAndroid Build Coastguard Worker pDat_1 = &pDat[L - 2];
526*e5436536SAndroid Build Coastguard Worker
527*e5436536SAndroid Build Coastguard Worker /* Sin and Cos values are 0.0f and 1.0f */
528*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[0];
529*e5436536SAndroid Build Coastguard Worker accu2 = pDat_1[1];
530*e5436536SAndroid Build Coastguard Worker
531*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -pDat_0[0];
532*e5436536SAndroid Build Coastguard Worker pDat_0[0] = pDat_0[1];
533*e5436536SAndroid Build Coastguard Worker
534*e5436536SAndroid Build Coastguard Worker for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) {
535*e5436536SAndroid Build Coastguard Worker FIXP_STP twd = sin_twiddle[idx];
536*e5436536SAndroid Build Coastguard Worker
537*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, accu1, accu2, twd);
538*e5436536SAndroid Build Coastguard Worker pDat_1[0] = -accu3;
539*e5436536SAndroid Build Coastguard Worker pDat_0[1] = -accu4;
540*e5436536SAndroid Build Coastguard Worker
541*e5436536SAndroid Build Coastguard Worker pDat_0 += 2;
542*e5436536SAndroid Build Coastguard Worker pDat_1 -= 2;
543*e5436536SAndroid Build Coastguard Worker
544*e5436536SAndroid Build Coastguard Worker cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd);
545*e5436536SAndroid Build Coastguard Worker
546*e5436536SAndroid Build Coastguard Worker accu1 = pDat_1[0];
547*e5436536SAndroid Build Coastguard Worker accu2 = pDat_1[1];
548*e5436536SAndroid Build Coastguard Worker
549*e5436536SAndroid Build Coastguard Worker pDat_0[0] = accu3;
550*e5436536SAndroid Build Coastguard Worker pDat_1[1] = -accu4;
551*e5436536SAndroid Build Coastguard Worker }
552*e5436536SAndroid Build Coastguard Worker
553*e5436536SAndroid Build Coastguard Worker if ((M & 1) == 0) {
554*e5436536SAndroid Build Coastguard Worker /* Last Sin and Cos value pair are the same */
555*e5436536SAndroid Build Coastguard Worker accu1 = fMult(accu1, WTC(0x5a82799a));
556*e5436536SAndroid Build Coastguard Worker accu2 = fMult(accu2, WTC(0x5a82799a));
557*e5436536SAndroid Build Coastguard Worker
558*e5436536SAndroid Build Coastguard Worker pDat_0[1] = -accu1 - accu2;
559*e5436536SAndroid Build Coastguard Worker pDat_1[0] = accu2 - accu1;
560*e5436536SAndroid Build Coastguard Worker }
561*e5436536SAndroid Build Coastguard Worker }
562*e5436536SAndroid Build Coastguard Worker
563*e5436536SAndroid Build Coastguard Worker /* Add twiddeling scale. */
564*e5436536SAndroid Build Coastguard Worker *pDat_e += 2;
565*e5436536SAndroid Build Coastguard Worker }
566*e5436536SAndroid Build Coastguard Worker #endif /* !defined(FUNCTION_dst_IV) */
567