Signed-off-by: Mans Rullgard <mans@mansr.com>
Mans Rullgard authored on 2011/03/31 05:13:21... | ... |
@@ -656,7 +656,7 @@ SKIPHEADERS += mpegaudio3.h |
656 | 656 |
|
657 | 657 |
EXAMPLES = api |
658 | 658 |
|
659 |
-TESTPROGS = cabac dct eval fft h264 iirfilter rangecoder snow |
|
659 |
+TESTPROGS = cabac dct eval fft fft-fixed h264 iirfilter rangecoder snow |
|
660 | 660 |
TESTPROGS-$(HAVE_MMX) += motion |
661 | 661 |
TESTOBJS = dctref.o |
662 | 662 |
|
663 | 663 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,20 @@ |
0 |
+/* |
|
1 |
+ * This file is part of Libav. |
|
2 |
+ * |
|
3 |
+ * Libav is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * Libav is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with Libav; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#define CONFIG_FFT_FLOAT 0 |
|
19 |
+#include "fft-test.c" |
... | ... |
@@ -27,8 +27,10 @@ |
27 | 27 |
#include "libavutil/lfg.h" |
28 | 28 |
#include "libavutil/log.h" |
29 | 29 |
#include "fft.h" |
30 |
+#if CONFIG_FFT_FLOAT |
|
30 | 31 |
#include "dct.h" |
31 | 32 |
#include "rdft.h" |
33 |
+#endif |
|
32 | 34 |
#include <math.h> |
33 | 35 |
#include <unistd.h> |
34 | 36 |
#include <sys/time.h> |
... | ... |
@@ -47,7 +49,19 @@ |
47 | 47 |
pim += (MUL16(are, bim) + MUL16(bre, aim));\ |
48 | 48 |
} |
49 | 49 |
|
50 |
-FFTComplex *exptab; |
|
50 |
+#if CONFIG_FFT_FLOAT |
|
51 |
+# define RANGE 1.0 |
|
52 |
+# define REF_SCALE(x, bits) (x) |
|
53 |
+# define FMT "%10.6f" |
|
54 |
+#else |
|
55 |
+# define RANGE 16384 |
|
56 |
+# define REF_SCALE(x, bits) ((x) / (1<<(bits))) |
|
57 |
+# define FMT "%6d" |
|
58 |
+#endif |
|
59 |
+ |
|
60 |
+struct { |
|
61 |
+ float re, im; |
|
62 |
+} *exptab; |
|
51 | 63 |
|
52 | 64 |
static void fft_ref_init(int nbits, int inverse) |
53 | 65 |
{ |
... | ... |
@@ -55,7 +69,7 @@ static void fft_ref_init(int nbits, int inverse) |
55 | 55 |
double c1, s1, alpha; |
56 | 56 |
|
57 | 57 |
n = 1 << nbits; |
58 |
- exptab = av_malloc((n / 2) * sizeof(FFTComplex)); |
|
58 |
+ exptab = av_malloc((n / 2) * sizeof(*exptab)); |
|
59 | 59 |
|
60 | 60 |
for (i = 0; i < (n/2); i++) { |
61 | 61 |
alpha = 2 * M_PI * (float)i / (float)n; |
... | ... |
@@ -92,12 +106,12 @@ static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) |
92 | 92 |
CMAC(tmp_re, tmp_im, c, s, q->re, q->im); |
93 | 93 |
q++; |
94 | 94 |
} |
95 |
- tabr[i].re = tmp_re; |
|
96 |
- tabr[i].im = tmp_im; |
|
95 |
+ tabr[i].re = REF_SCALE(tmp_re, nbits); |
|
96 |
+ tabr[i].im = REF_SCALE(tmp_im, nbits); |
|
97 | 97 |
} |
98 | 98 |
} |
99 | 99 |
|
100 |
-static void imdct_ref(float *out, float *in, int nbits) |
|
100 |
+static void imdct_ref(FFTSample *out, FFTSample *in, int nbits) |
|
101 | 101 |
{ |
102 | 102 |
int n = 1<<nbits; |
103 | 103 |
int k, i, a; |
... | ... |
@@ -110,12 +124,12 @@ static void imdct_ref(float *out, float *in, int nbits) |
110 | 110 |
f = cos(M_PI * a / (double)(2 * n)); |
111 | 111 |
sum += f * in[k]; |
112 | 112 |
} |
113 |
- out[i] = -sum; |
|
113 |
+ out[i] = REF_SCALE(-sum, nbits - 2); |
|
114 | 114 |
} |
115 | 115 |
} |
116 | 116 |
|
117 | 117 |
/* NOTE: no normalisation by 1 / N is done */ |
118 |
-static void mdct_ref(float *output, float *input, int nbits) |
|
118 |
+static void mdct_ref(FFTSample *output, FFTSample *input, int nbits) |
|
119 | 119 |
{ |
120 | 120 |
int n = 1<<nbits; |
121 | 121 |
int k, i; |
... | ... |
@@ -128,10 +142,11 @@ static void mdct_ref(float *output, float *input, int nbits) |
128 | 128 |
a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n)); |
129 | 129 |
s += input[i] * cos(a); |
130 | 130 |
} |
131 |
- output[k] = s; |
|
131 |
+ output[k] = REF_SCALE(s, nbits - 1); |
|
132 | 132 |
} |
133 | 133 |
} |
134 | 134 |
|
135 |
+#if CONFIG_FFT_FLOAT |
|
135 | 136 |
static void idct_ref(float *output, float *input, int nbits) |
136 | 137 |
{ |
137 | 138 |
int n = 1<<nbits; |
... | ... |
@@ -164,11 +179,12 @@ static void dct_ref(float *output, float *input, int nbits) |
164 | 164 |
output[k] = s; |
165 | 165 |
} |
166 | 166 |
} |
167 |
+#endif |
|
167 | 168 |
|
168 | 169 |
|
169 |
-static float frandom(AVLFG *prng) |
|
170 |
+static FFTSample frandom(AVLFG *prng) |
|
170 | 171 |
{ |
171 |
- return (int16_t)av_lfg_get(prng) / 32768.0; |
|
172 |
+ return (int16_t)av_lfg_get(prng) / 32768.0 * RANGE; |
|
172 | 173 |
} |
173 | 174 |
|
174 | 175 |
static int64_t gettime(void) |
... | ... |
@@ -178,7 +194,7 @@ static int64_t gettime(void) |
178 | 178 |
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; |
179 | 179 |
} |
180 | 180 |
|
181 |
-static int check_diff(float *tab1, float *tab2, int n, double scale) |
|
181 |
+static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale) |
|
182 | 182 |
{ |
183 | 183 |
int i; |
184 | 184 |
double max= 0; |
... | ... |
@@ -186,9 +202,9 @@ static int check_diff(float *tab1, float *tab2, int n, double scale) |
186 | 186 |
int err = 0; |
187 | 187 |
|
188 | 188 |
for (i = 0; i < n; i++) { |
189 |
- double e= fabsf(tab1[i] - (tab2[i] / scale)); |
|
189 |
+ double e = fabsf(tab1[i] - (tab2[i] / scale)) / RANGE; |
|
190 | 190 |
if (e >= 1e-3) { |
191 |
- av_log(NULL, AV_LOG_ERROR, "ERROR %5d: %10.6f %10.6f\n", |
|
191 |
+ av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n", |
|
192 | 192 |
i, tab1[i], tab2[i]); |
193 | 193 |
err = 1; |
194 | 194 |
} |
... | ... |
@@ -233,8 +249,10 @@ int main(int argc, char **argv) |
233 | 233 |
int do_inverse = 0; |
234 | 234 |
FFTContext s1, *s = &s1; |
235 | 235 |
FFTContext m1, *m = &m1; |
236 |
+#if CONFIG_FFT_FLOAT |
|
236 | 237 |
RDFTContext r1, *r = &r1; |
237 | 238 |
DCTContext d1, *d = &d1; |
239 |
+#endif |
|
238 | 240 |
int fft_nbits, fft_size, fft_size_2; |
239 | 241 |
double scale = 1.0; |
240 | 242 |
AVLFG prng; |
... | ... |
@@ -297,6 +315,7 @@ int main(int argc, char **argv) |
297 | 297 |
ff_fft_init(s, fft_nbits, do_inverse); |
298 | 298 |
fft_ref_init(fft_nbits, do_inverse); |
299 | 299 |
break; |
300 |
+#if CONFIG_FFT_FLOAT |
|
300 | 301 |
case TRANSFORM_RDFT: |
301 | 302 |
if (do_inverse) |
302 | 303 |
av_log(NULL, AV_LOG_INFO,"IDFT_C2R"); |
... | ... |
@@ -312,6 +331,10 @@ int main(int argc, char **argv) |
312 | 312 |
av_log(NULL, AV_LOG_INFO,"DCT_II"); |
313 | 313 |
ff_dct_init(d, fft_nbits, do_inverse ? DCT_III : DCT_II); |
314 | 314 |
break; |
315 |
+#endif |
|
316 |
+ default: |
|
317 |
+ av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); |
|
318 |
+ return 1; |
|
315 | 319 |
} |
316 | 320 |
av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); |
317 | 321 |
|
... | ... |
@@ -328,15 +351,15 @@ int main(int argc, char **argv) |
328 | 328 |
switch (transform) { |
329 | 329 |
case TRANSFORM_MDCT: |
330 | 330 |
if (do_inverse) { |
331 |
- imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); |
|
332 |
- m->imdct_calc(m, tab2, (float *)tab1); |
|
333 |
- err = check_diff((float *)tab_ref, tab2, fft_size, scale); |
|
331 |
+ imdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); |
|
332 |
+ m->imdct_calc(m, tab2, (FFTSample *)tab1); |
|
333 |
+ err = check_diff((FFTSample *)tab_ref, tab2, fft_size, scale); |
|
334 | 334 |
} else { |
335 |
- mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); |
|
335 |
+ mdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); |
|
336 | 336 |
|
337 |
- m->mdct_calc(m, tab2, (float *)tab1); |
|
337 |
+ m->mdct_calc(m, tab2, (FFTSample *)tab1); |
|
338 | 338 |
|
339 |
- err = check_diff((float *)tab_ref, tab2, fft_size / 2, scale); |
|
339 |
+ err = check_diff((FFTSample *)tab_ref, tab2, fft_size / 2, scale); |
|
340 | 340 |
} |
341 | 341 |
break; |
342 | 342 |
case TRANSFORM_FFT: |
... | ... |
@@ -345,8 +368,9 @@ int main(int argc, char **argv) |
345 | 345 |
s->fft_calc(s, tab); |
346 | 346 |
|
347 | 347 |
fft_ref(tab_ref, tab1, fft_nbits); |
348 |
- err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 1.0); |
|
348 |
+ err = check_diff((FFTSample *)tab_ref, (FFTSample *)tab, fft_size * 2, 1.0); |
|
349 | 349 |
break; |
350 |
+#if CONFIG_FFT_FLOAT |
|
350 | 351 |
case TRANSFORM_RDFT: |
351 | 352 |
if (do_inverse) { |
352 | 353 |
tab1[ 0].im = 0; |
... | ... |
@@ -387,6 +411,7 @@ int main(int argc, char **argv) |
387 | 387 |
} |
388 | 388 |
err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); |
389 | 389 |
break; |
390 |
+#endif |
|
390 | 391 |
} |
391 | 392 |
|
392 | 393 |
/* do a speed test */ |
... | ... |
@@ -404,15 +429,16 @@ int main(int argc, char **argv) |
404 | 404 |
switch (transform) { |
405 | 405 |
case TRANSFORM_MDCT: |
406 | 406 |
if (do_inverse) { |
407 |
- m->imdct_calc(m, (float *)tab, (float *)tab1); |
|
407 |
+ m->imdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); |
|
408 | 408 |
} else { |
409 |
- m->mdct_calc(m, (float *)tab, (float *)tab1); |
|
409 |
+ m->mdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); |
|
410 | 410 |
} |
411 | 411 |
break; |
412 | 412 |
case TRANSFORM_FFT: |
413 | 413 |
memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); |
414 | 414 |
s->fft_calc(s, tab); |
415 | 415 |
break; |
416 |
+#if CONFIG_FFT_FLOAT |
|
416 | 417 |
case TRANSFORM_RDFT: |
417 | 418 |
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
418 | 419 |
r->rdft_calc(r, tab2); |
... | ... |
@@ -421,6 +447,7 @@ int main(int argc, char **argv) |
421 | 421 |
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
422 | 422 |
d->dct_calc(d, tab2); |
423 | 423 |
break; |
424 |
+#endif |
|
424 | 425 |
} |
425 | 426 |
} |
426 | 427 |
duration = gettime() - time_start; |
... | ... |
@@ -441,12 +468,14 @@ int main(int argc, char **argv) |
441 | 441 |
case TRANSFORM_FFT: |
442 | 442 |
ff_fft_end(s); |
443 | 443 |
break; |
444 |
+#if CONFIG_FFT_FLOAT |
|
444 | 445 |
case TRANSFORM_RDFT: |
445 | 446 |
ff_rdft_end(r); |
446 | 447 |
break; |
447 | 448 |
case TRANSFORM_DCT: |
448 | 449 |
ff_dct_end(d); |
449 | 450 |
break; |
451 |
+#endif |
|
450 | 452 |
} |
451 | 453 |
|
452 | 454 |
av_free(tab); |