1 /*
2 * (c) 2002 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * FFT and MDCT tests.
24 */
25
32 #if CONFIG_FFT_FLOAT
35 #endif
36 #include <math.h>
37 #if HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 /* reference fft */
45
46 #define MUL16(a,b) ((a) * (b))
47
48 #define CMAC(pre, pim, are, aim, bre, bim) \
49 {\
50 pre += (MUL16(are, bre) - MUL16(aim, bim));\
51 pim += (MUL16(are, bim) + MUL16(bre, aim));\
52 }
53
54 #if CONFIG_FFT_FLOAT
56 # define REF_SCALE(x, bits) (x)
58 #elif CONFIG_FFT_FIXED_32
59 # define RANGE 8388608
60 # define REF_SCALE(x, bits) (x)
61 # define FMT "%6d"
62 #else
63 # define RANGE 16384
64 # define REF_SCALE(x, bits) ((x) / (1<<(bits)))
65 # define FMT "%6d"
66 #endif
67
68 struct {
71
73 {
76
77 n = 1 << nbits;
79
80 for (i = 0; i < (n/2); i++) {
81 alpha = 2 *
M_PI * (float)i / (
float)
n;
82 c1 = cos(alpha);
83 s1 = sin(alpha);
84 if (!inverse)
88 }
89 }
90
92 {
94 double tmp_re, tmp_im,
s,
c;
96
97 n = 1 << nbits;
98 n2 = n >> 1;
99 for (i = 0; i <
n; i++) {
100 tmp_re = 0;
101 tmp_im = 0;
103 for (j = 0; j <
n; j++) {
104 k = (i * j) & (n - 1);
105 if (k >= n2) {
108 } else {
111 }
112 CMAC(tmp_re, tmp_im, c, s, q->
re, q->
im);
113 q++;
114 }
117 }
118 }
119
121 {
124 double sum, f;
125
126 for (i = 0; i <
n; i++) {
127 sum = 0;
128 for (k = 0; k < n/2; k++) {
129 a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
130 f = cos(
M_PI * a / (
double)(2 * n));
131 sum += f * in[k];
132 }
134 }
135 }
136
137 /* NOTE: no normalisation by 1 / N is done */
139 {
141 int k, i;
143
144 /* do it by hand */
145 for (k = 0; k < n/2; k++) {
146 s = 0;
147 for (i = 0; i <
n; i++) {
148 a = (2*
M_PI*(2*i+1+n/2)*(2*k+1) / (4 *
n));
149 s += input[i] * cos(a);
150 }
152 }
153 }
154
155 #if CONFIG_FFT_FLOAT
157 {
159 int k, i;
161
162 /* do it by hand */
163 for (i = 0; i <
n; i++) {
164 s = 0.5 * input[0];
165 for (k = 1; k <
n; k++) {
166 a =
M_PI*k*(i+0.5) /
n;
167 s += input[k] * cos(a);
168 }
169 output[i] = 2 * s /
n;
170 }
171 }
173 {
175 int k, i;
177
178 /* do it by hand */
179 for (k = 0; k <
n; k++) {
180 s = 0;
181 for (i = 0; i <
n; i++) {
182 a =
M_PI*k*(i+0.5) /
n;
183 s += input[i] * cos(a);
184 }
186 }
187 }
188 #endif
189
190
192 {
194 }
195
197 {
198 int i;
199 double max= 0;
200 double error= 0;
201 int err = 0;
202
203 for (i = 0; i <
n; i++) {
204 double e = fabsf(tab1[i] - (tab2[i] / scale)) /
RANGE;
205 if (e >= 1e-3) {
207 i, tab1[i], tab2[i]);
208 err = 1;
209 }
210 error+= e*e;
211 if(e>max) max= e;
212 }
214 return err;
215 }
216
217
219 {
221 "-h print this help\n"
222 "-s speed test\n"
223 "-m (I)MDCT test\n"
224 "-d (I)DCT test\n"
225 "-r (I)RDFT test\n"
226 "-i inverse transform test\n"
227 "-n b set the transform size to 2^b\n"
228 "-f x set scale factor for output data of (I)MDCT to x\n"
229 );
230 }
231
237 };
238
239 #if !HAVE_GETOPT
241 #endif
242
243 int main(
int argc,
char **argv)
244 {
248 int cpuflags;
249 int do_speed = 0;
250 int err = 1;
252 int do_inverse = 0;
255 #if CONFIG_FFT_FLOAT
258 int fft_size_2;
259 #endif
260 int fft_nbits, fft_size;
264
265 fft_nbits = 9;
266 for(;;) {
267 c =
getopt(argc, argv,
"hsimrdn:f:c:");
268 if (c == -1)
269 break;
270 switch(c) {
271 case 'h':
273 return 1;
274 case 's':
275 do_speed = 1;
276 break;
277 case 'i':
278 do_inverse = 1;
279 break;
280 case 'm':
282 break;
283 case 'r':
285 break;
286 case 'd':
288 break;
289 case 'n':
291 break;
292 case 'f':
294 break;
295 case 'c':
297
299 return 1;
300
302 break;
303 }
304 }
305
306 fft_size = 1 << fft_nbits;
311
312 switch (transform) {
315 if (do_inverse)
317 else
320 break;
322 if (do_inverse)
324 else
328 break;
329 #if CONFIG_FFT_FLOAT
331 if (do_inverse)
333 else
337 break;
338 # if CONFIG_DCT
340 if (do_inverse)
342 else
345 break;
346 # endif
347 #endif
348 default:
350 return 1;
351 }
353
354 /* generate random data */
355
356 for (i = 0; i < fft_size; i++) {
359 }
360
361 /* checking result */
363
364 switch (transform) {
366 if (do_inverse) {
370 } else {
372
374
376 }
377 break;
379 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
382
383 fft_ref(tab_ref, tab1, fft_nbits);
385 break;
386 #if CONFIG_FFT_FLOAT
388 fft_size_2 = fft_size >> 1;
389 if (do_inverse) {
391 tab1[fft_size_2].
im = 0;
392 for (i = 1; i < fft_size_2; i++) {
393 tab1[fft_size_2+i].
re = tab1[fft_size_2-i].
re;
394 tab1[fft_size_2+i].
im = -tab1[fft_size_2-i].
im;
395 }
396
397 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
398 tab2[1] = tab1[fft_size_2].
re;
399
401 fft_ref(tab_ref, tab1, fft_nbits);
402 for (i = 0; i < fft_size; i++) {
405 }
406 err =
check_diff((
float *)tab_ref, (
float *)tab, fft_size * 2, 0.5);
407 } else {
408 for (i = 0; i < fft_size; i++) {
409 tab2[i] = tab1[i].
re;
411 }
413 fft_ref(tab_ref, tab1, fft_nbits);
414 tab_ref[0].
im = tab_ref[fft_size_2].
re;
415 err =
check_diff((
float *)tab_ref, (
float *)tab2, fft_size, 1.0);
416 }
417 break;
419 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
421 if (do_inverse) {
423 } else {
425 }
426 err =
check_diff((
float *)tab_ref, (
float *)tab, fft_size, 1.0);
427 break;
428 #endif
429 }
430
431 /* do a speed test */
432
433 if (do_speed) {
435 int nb_its;
436
438 /* we measure during about 1 seconds */
439 nb_its = 1;
440 for(;;) {
442 for (it = 0; it < nb_its; it++) {
443 switch (transform) {
445 if (do_inverse) {
447 } else {
449 }
450 break;
452 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
454 break;
455 #if CONFIG_FFT_FLOAT
457 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
459 break;
461 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
463 break;
464 #endif
465 }
466 }
468 if (duration >= 1000000)
469 break;
470 nb_its *= 2;
471 }
472 av_log(NULL,
AV_LOG_INFO,
"time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
473 (double)duration / nb_its,
474 (double)duration / 1000000.0,
475 nb_its);
476 }
477
478 switch (transform) {
481 break;
484 break;
485 #if CONFIG_FFT_FLOAT
488 break;
489 # if CONFIG_DCT
492 break;
493 # endif
494 #endif
495 }
496
502
503 if (err)
504 printf("Error: %d.\n", err);
505
506 return !!err;
507 }