summaryrefslogtreecommitdiff
path: root/apps/codecs/libatrac/mdct.c
diff options
context:
space:
mode:
authorMohamed Tarek <mt@rockbox.org>2009-08-10 14:46:31 +0000
committerMohamed Tarek <mt@rockbox.org>2009-08-10 14:46:31 +0000
commit519adfbaae5933ec18d2e3cb77e690e36cd49916 (patch)
tree8303456ddf72f2ff5da2b9a99802c73e1409fc28 /apps/codecs/libatrac/mdct.c
parent1c0aeb18ca264e1f64e31f219189afab442676eb (diff)
downloadrockbox-519adfbaae5933ec18d2e3cb77e690e36cd49916.tar.gz
rockbox-519adfbaae5933ec18d2e3cb77e690e36cd49916.zip
Import libatrac from ffmpeg and modify librm to support ATRAC3.
The decoder is still in floating point. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22235 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libatrac/mdct.c')
-rw-r--r--apps/codecs/libatrac/mdct.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/apps/codecs/libatrac/mdct.c b/apps/codecs/libatrac/mdct.c
new file mode 100644
index 0000000000..670b6d381e
--- /dev/null
+++ b/apps/codecs/libatrac/mdct.c
@@ -0,0 +1,245 @@
1/*
2 * MDCT/IMDCT transforms
3 * Copyright (c) 2002 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include "dsputil.h"
22
23#ifndef M_E
24#define M_E 2.7182818284590452354 /* e */
25#endif
26#ifndef M_LN2
27#define M_LN2 0.69314718055994530942 /* log_e 2 */
28#endif
29#ifndef M_LN10
30#define M_LN10 2.30258509299404568402 /* log_e 10 */
31#endif
32#ifndef M_PI
33#define M_PI 3.14159265358979323846 /* pi */
34#endif
35#ifndef M_SQRT1_2
36#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
37#endif
38
39/**
40 * @file libavcodec/mdct.c
41 * MDCT/IMDCT transforms.
42 */
43
44// Generate a Kaiser-Bessel Derived Window.
45#define BESSEL_I0_ITER 50 // default: 50 iterations of Bessel I0 approximation
46av_cold void ff_kbd_window_init(float *window, float alpha, int n)
47{
48 int i, j;
49 double sum = 0.0, bessel, tmp;
50 double local_window[n];
51 double alpha2 = (alpha * M_PI / n) * (alpha * M_PI / n);
52
53 for (i = 0; i < n; i++) {
54 tmp = i * (n - i) * alpha2;
55 bessel = 1.0;
56 for (j = BESSEL_I0_ITER; j > 0; j--)
57 bessel = bessel * tmp / (j * j) + 1;
58 sum += bessel;
59 local_window[i] = sum;
60 }
61
62 sum++;
63 for (i = 0; i < n; i++)
64 window[i] = sqrt(local_window[i] / sum);
65}
66
67DECLARE_ALIGNED(16, float, ff_sine_128 [ 128]);
68DECLARE_ALIGNED(16, float, ff_sine_256 [ 256]);
69DECLARE_ALIGNED(16, float, ff_sine_512 [ 512]);
70DECLARE_ALIGNED(16, float, ff_sine_1024[1024]);
71DECLARE_ALIGNED(16, float, ff_sine_2048[2048]);
72DECLARE_ALIGNED(16, float, ff_sine_4096[4096]);
73float *ff_sine_windows[6] = {
74 ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, ff_sine_2048, ff_sine_4096
75};
76
77// Generate a sine window.
78av_cold void ff_sine_window_init(float *window, int n) {
79 int i;
80 for(i = 0; i < n; i++)
81 window[i] = sinf((i + 0.5) * (M_PI / (2.0 * n)));
82}
83
84/**
85 * init MDCT or IMDCT computation.
86 */
87av_cold int ff_mdct_init(MDCTContext *s, int nbits, int inverse)
88{
89 int n, n4, i;
90 double alpha;
91
92 memset(s, 0, sizeof(*s));
93 n = 1 << nbits;
94 s->nbits = nbits;
95 s->n = n;
96 n4 = n >> 2;
97 s->tcos = av_malloc(n4 * sizeof(FFTSample));
98 if (!s->tcos)
99 goto fail;
100 s->tsin = av_malloc(n4 * sizeof(FFTSample));
101 if (!s->tsin)
102 goto fail;
103
104 for(i=0;i<n4;i++) {
105 alpha = 2 * M_PI * (i + 1.0 / 8.0) / n;
106 s->tcos[i] = -cos(alpha);
107 s->tsin[i] = -sin(alpha);
108 }
109 if (ff_fft_init(&s->fft, s->nbits - 2, inverse) < 0)
110 goto fail;
111 return 0;
112 fail:
113 av_freep(&s->tcos);
114 av_freep(&s->tsin);
115 return -1;
116}
117
118/* complex multiplication: p = a * b */
119#define CMUL(pre, pim, are, aim, bre, bim) \
120{\
121 FFTSample _are = (are);\
122 FFTSample _aim = (aim);\
123 FFTSample _bre = (bre);\
124 FFTSample _bim = (bim);\
125 (pre) = _are * _bre - _aim * _bim;\
126 (pim) = _are * _bim + _aim * _bre;\
127}
128
129/**
130 * Compute the middle half of the inverse MDCT of size N = 2^nbits,
131 * thus excluding the parts that can be derived by symmetry
132 * @param output N/2 samples
133 * @param input N/2 samples
134 */
135void ff_imdct_half_c(MDCTContext *s, FFTSample *output, const FFTSample *input)
136{
137 int k, n8, n4, n2, n, j;
138 const uint16_t *revtab = s->fft.revtab;
139 const FFTSample *tcos = s->tcos;
140 const FFTSample *tsin = s->tsin;
141 const FFTSample *in1, *in2;
142 FFTComplex *z = (FFTComplex *)output;
143
144 n = 1 << s->nbits;
145 n2 = n >> 1;
146 n4 = n >> 2;
147 n8 = n >> 3;
148
149 /* pre rotation */
150 in1 = input;
151 in2 = input + n2 - 1;
152 for(k = 0; k < n4; k++) {
153 j=revtab[k];
154 CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
155 in1 += 2;
156 in2 -= 2;
157 }
158 ff_fft_calc(&s->fft, z);
159
160 /* post rotation + reordering */
161 output += n4;
162 for(k = 0; k < n8; k++) {
163 FFTSample r0, i0, r1, i1;
164 CMUL(r0, i1, z[n8-k-1].im, z[n8-k-1].re, tsin[n8-k-1], tcos[n8-k-1]);
165 CMUL(r1, i0, z[n8+k ].im, z[n8+k ].re, tsin[n8+k ], tcos[n8+k ]);
166 z[n8-k-1].re = r0;
167 z[n8-k-1].im = i0;
168 z[n8+k ].re = r1;
169 z[n8+k ].im = i1;
170 }
171}
172
173/**
174 * Compute inverse MDCT of size N = 2^nbits
175 * @param output N samples
176 * @param input N/2 samples
177 */
178void ff_imdct_calc_c(MDCTContext *s, FFTSample *output, const FFTSample *input)
179{
180 int k;
181 int n = 1 << s->nbits;
182 int n2 = n >> 1;
183 int n4 = n >> 2;
184
185 ff_imdct_half_c(s, output+n4, input);
186
187 for(k = 0; k < n4; k++) {
188 output[k] = -output[n2-k-1];
189 output[n-k-1] = output[n2+k];
190 }
191}
192
193/**
194 * Compute MDCT of size N = 2^nbits
195 * @param input N samples
196 * @param out N/2 samples
197 */
198void ff_mdct_calc(MDCTContext *s, FFTSample *out, const FFTSample *input)
199{
200 int i, j, n, n8, n4, n2, n3;
201 FFTSample re, im;
202 const uint16_t *revtab = s->fft.revtab;
203 const FFTSample *tcos = s->tcos;
204 const FFTSample *tsin = s->tsin;
205 FFTComplex *x = (FFTComplex *)out;
206
207 n = 1 << s->nbits;
208 n2 = n >> 1;
209 n4 = n >> 2;
210 n8 = n >> 3;
211 n3 = 3 * n4;
212
213 /* pre rotation */
214 for(i=0;i<n8;i++) {
215 re = -input[2*i+3*n4] - input[n3-1-2*i];
216 im = -input[n4+2*i] + input[n4-1-2*i];
217 j = revtab[i];
218 CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
219
220 re = input[2*i] - input[n2-1-2*i];
221 im = -(input[n2+2*i] + input[n-1-2*i]);
222 j = revtab[n8 + i];
223 CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
224 }
225
226 ff_fft_calc(&s->fft, x);
227
228 /* post rotation */
229 for(i=0;i<n8;i++) {
230 FFTSample r0, i0, r1, i1;
231 CMUL(i1, r0, x[n8-i-1].re, x[n8-i-1].im, -tsin[n8-i-1], -tcos[n8-i-1]);
232 CMUL(i0, r1, x[n8+i ].re, x[n8+i ].im, -tsin[n8+i ], -tcos[n8+i ]);
233 x[n8-i-1].re = r0;
234 x[n8-i-1].im = i0;
235 x[n8+i ].re = r1;
236 x[n8+i ].im = i1;
237 }
238}
239
240av_cold void ff_mdct_end(MDCTContext *s)
241{
242 av_freep(&s->tcos);
243 av_freep(&s->tsin);
244 ff_fft_end(&s->fft);
245}