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 <stdlib.h>
41 #include <string.h>
42
43 /* reference fft */
44
45 #define MUL16(a,b) ((a) * (b))
46
47 #define CMAC(pre, pim, are, aim, bre, bim) \
48 {\
49 pre += (MUL16(are, bre) - MUL16(aim, bim));\
50 pim += (MUL16(are, bim) + MUL16(bre, aim));\
51 }
52
53 #if CONFIG_FFT_FLOAT
55 # define REF_SCALE(x, bits) (x)
57 #else
58 # define RANGE 16384
59 # define REF_SCALE(x, bits) ((x) / (1<<(bits)))
60 # define FMT "%6d"
61 #endif
62
63 struct {
66
68 {
71
72 n = 1 << nbits;
74
75 for (i = 0; i < (n/2); i++) {
76 alpha = 2 *
M_PI * (float)i / (
float)
n;
77 c1 = cos(alpha);
78 s1 = sin(alpha);
79 if (!inverse)
83 }
84 }
85
87 {
89 double tmp_re, tmp_im,
s,
c;
91
92 n = 1 << nbits;
93 n2 = n >> 1;
94 for (i = 0; i <
n; i++) {
95 tmp_re = 0;
96 tmp_im = 0;
98 for (j = 0; j <
n; j++) {
99 k = (i * j) & (n - 1);
100 if (k >= n2) {
103 } else {
106 }
107 CMAC(tmp_re, tmp_im, c, s, q->
re, q->
im);
108 q++;
109 }
112 }
113 }
114
116 {
119 double sum, f;
120
121 for (i = 0; i <
n; i++) {
122 sum = 0;
123 for (k = 0; k < n/2; k++) {
124 a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
125 f = cos(
M_PI * a / (
double)(2 * n));
126 sum += f * in[k];
127 }
129 }
130 }
131
132 /* NOTE: no normalisation by 1 / N is done */
134 {
136 int k, i;
138
139 /* do it by hand */
140 for (k = 0; k < n/2; k++) {
141 s = 0;
142 for (i = 0; i <
n; i++) {
143 a = (2*
M_PI*(2*i+1+n/2)*(2*k+1) / (4 *
n));
144 s += input[i] * cos(a);
145 }
147 }
148 }
149
150 #if CONFIG_FFT_FLOAT
152 {
154 int k, i;
156
157 /* do it by hand */
158 for (i = 0; i <
n; i++) {
159 s = 0.5 * input[0];
160 for (k = 1; k <
n; k++) {
161 a =
M_PI*k*(i+0.5) /
n;
162 s += input[k] * cos(a);
163 }
164 output[i] = 2 * s /
n;
165 }
166 }
168 {
170 int k, i;
172
173 /* do it by hand */
174 for (k = 0; k <
n; k++) {
175 s = 0;
176 for (i = 0; i <
n; i++) {
177 a =
M_PI*k*(i+0.5) /
n;
178 s += input[i] * cos(a);
179 }
181 }
182 }
183 #endif
184
185
187 {
189 }
190
192 {
193 int i;
194 double max= 0;
195 double error= 0;
196 int err = 0;
197
198 for (i = 0; i <
n; i++) {
199 double e = fabsf(tab1[i] - (tab2[i] / scale)) /
RANGE;
200 if (e >= 1e-3) {
202 i, tab1[i], tab2[i]);
203 err = 1;
204 }
205 error+= e*e;
206 if(e>max) max= e;
207 }
209 return err;
210 }
211
212
214 {
216 "-h print this help\n"
217 "-s speed test\n"
218 "-m (I)MDCT test\n"
219 "-d (I)DCT test\n"
220 "-r (I)RDFT test\n"
221 "-i inverse transform test\n"
222 "-n b set the transform size to 2^b\n"
223 "-f x set scale factor for output data of (I)MDCT to x\n"
224 );
225 }
226
232 };
233
234 #if !HAVE_GETOPT
236 #endif
237
238 int main(
int argc,
char **argv)
239 {
243 int cpuflags;
244 int do_speed = 0;
245 int err = 1;
247 int do_inverse = 0;
250 #if CONFIG_FFT_FLOAT
253 int fft_size_2;
254 #endif
255 int fft_nbits, fft_size;
259
260 fft_nbits = 9;
261 for(;;) {
262 c =
getopt(argc, argv,
"hsimrdn:f:c:");
263 if (c == -1)
264 break;
265 switch(c) {
266 case 'h':
268 return 1;
269 case 's':
270 do_speed = 1;
271 break;
272 case 'i':
273 do_inverse = 1;
274 break;
275 case 'm':
277 break;
278 case 'r':
280 break;
281 case 'd':
283 break;
284 case 'n':
286 break;
287 case 'f':
289 break;
290 case 'c':
292
294 return 1;
295
297 break;
298 }
299 }
300
301 fft_size = 1 << fft_nbits;
306
307 switch (transform) {
310 if (do_inverse)
312 else
315 break;
317 if (do_inverse)
319 else
323 break;
324 #if CONFIG_FFT_FLOAT
326 if (do_inverse)
328 else
332 break;
334 if (do_inverse)
336 else
339 break;
340 #endif
341 default:
343 return 1;
344 }
346
347 /* generate random data */
348
349 for (i = 0; i < fft_size; i++) {
352 }
353
354 /* checking result */
356
357 switch (transform) {
359 if (do_inverse) {
363 } else {
365
367
369 }
370 break;
372 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
375
376 fft_ref(tab_ref, tab1, fft_nbits);
378 break;
379 #if CONFIG_FFT_FLOAT
381 fft_size_2 = fft_size >> 1;
382 if (do_inverse) {
384 tab1[fft_size_2].
im = 0;
385 for (i = 1; i < fft_size_2; i++) {
386 tab1[fft_size_2+i].
re = tab1[fft_size_2-i].
re;
387 tab1[fft_size_2+i].
im = -tab1[fft_size_2-i].
im;
388 }
389
390 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
391 tab2[1] = tab1[fft_size_2].
re;
392
394 fft_ref(tab_ref, tab1, fft_nbits);
395 for (i = 0; i < fft_size; i++) {
398 }
399 err =
check_diff((
float *)tab_ref, (
float *)tab, fft_size * 2, 0.5);
400 } else {
401 for (i = 0; i < fft_size; i++) {
402 tab2[i] = tab1[i].
re;
404 }
406 fft_ref(tab_ref, tab1, fft_nbits);
407 tab_ref[0].
im = tab_ref[fft_size_2].
re;
408 err =
check_diff((
float *)tab_ref, (
float *)tab2, fft_size, 1.0);
409 }
410 break;
412 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
414 if (do_inverse) {
416 } else {
418 }
419 err =
check_diff((
float *)tab_ref, (
float *)tab, fft_size, 1.0);
420 break;
421 #endif
422 }
423
424 /* do a speed test */
425
426 if (do_speed) {
428 int nb_its;
429
431 /* we measure during about 1 seconds */
432 nb_its = 1;
433 for(;;) {
435 for (it = 0; it < nb_its; it++) {
436 switch (transform) {
438 if (do_inverse) {
440 } else {
442 }
443 break;
445 memcpy(tab, tab1, fft_size *
sizeof(
FFTComplex));
447 break;
448 #if CONFIG_FFT_FLOAT
450 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
452 break;
454 memcpy(tab2, tab1, fft_size *
sizeof(
FFTSample));
456 break;
457 #endif
458 }
459 }
461 if (duration >= 1000000)
462 break;
463 nb_its *= 2;
464 }
465 av_log(NULL,
AV_LOG_INFO,
"time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
466 (double)duration / nb_its,
467 (double)duration / 1000000.0,
468 nb_its);
469 }
470
471 switch (transform) {
474 break;
477 break;
478 #if CONFIG_FFT_FLOAT
481 break;
484 break;
485 #endif
486 }
487
493
494 return err;
495 }