]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/fft-test.c
suppressed getopt.h
[frescor/ffmpeg.git] / libavcodec / fft-test.c
1 /* FFT and MDCT tests */
2 #include "dsputil.h"
3 #include <math.h>
4 #include <unistd.h>
5 #include <sys/time.h>
6
7 int mm_flags;
8
9 /* reference fft */
10
11 #define MUL16(a,b) ((a) * (b))
12
13 #define CMAC(pre, pim, are, aim, bre, bim) \
14 {\
15    pre += (MUL16(are, bre) - MUL16(aim, bim));\
16    pim += (MUL16(are, bim) + MUL16(bre, aim));\
17 }
18
19 FFTComplex *exptab;
20
21 void fft_ref_init(int nbits, int inverse)
22 {
23     int n, i;
24     float c1, s1, alpha;
25
26     n = 1 << nbits;
27     exptab = av_malloc((n / 2) * sizeof(FFTComplex));
28
29     for(i=0;i<(n/2);i++) {
30         alpha = 2 * M_PI * (float)i / (float)n;
31         c1 = cos(alpha);
32         s1 = sin(alpha);
33         if (!inverse)
34             s1 = -s1;
35         exptab[i].re = c1;
36         exptab[i].im = s1;
37     }
38 }
39
40 void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
41 {
42     int n, i, j, k, n2;
43     float tmp_re, tmp_im, s, c;
44     FFTComplex *q;
45
46     n = 1 << nbits;
47     n2 = n >> 1;
48     for(i=0;i<n;i++) {
49         tmp_re = 0;
50         tmp_im = 0;
51         q = tab;
52         for(j=0;j<n;j++) {
53             k = (i * j) & (n - 1);
54             if (k >= n2) {
55                 c = -exptab[k - n2].re;
56                 s = -exptab[k - n2].im;
57             } else {
58                 c = exptab[k].re;
59                 s = exptab[k].im;
60             }
61             CMAC(tmp_re, tmp_im, c, s, q->re, q->im);
62             q++;
63         }
64         tabr[i].re = tmp_re;
65         tabr[i].im = tmp_im;
66     }
67 }
68
69 void imdct_ref(float *out, float *in, int n)
70 {
71     int k, i, a;
72     float sum, f;
73
74     for(i=0;i<n;i++) {
75         sum = 0;
76         for(k=0;k<n/2;k++) {
77             a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
78             f = cos(M_PI * a / (double)(2 * n));
79             sum += f * in[k];
80         }
81         out[i] = -sum;
82     }
83 }
84
85 /* NOTE: no normalisation by 1 / N is done */
86 void mdct_ref(float *output, float *input, int n)
87 {
88     int k, i;
89     float a, s;
90
91     /* do it by hand */
92     for(k=0;k<n/2;k++) {
93         s = 0;
94         for(i=0;i<n;i++) {
95             a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n));
96             s += input[i] * cos(a);
97         }
98         output[k] = s;
99     }
100 }
101
102
103 float frandom(void)
104 {
105     return (float)((random() & 0xffff) - 32768) / 32768.0;
106 }
107
108 INT64 gettime(void)
109 {
110     struct timeval tv;
111     gettimeofday(&tv,NULL);
112     return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
113 }
114
115 void check_diff(float *tab1, float *tab2, int n)
116 {
117     int i;
118
119     for(i=0;i<n;i++) {
120         if (fabsf(tab1[i] - tab2[i]) >= 1e-3) {
121             printf("ERROR %d: %f %f\n", 
122                    i, tab1[i], tab2[i]);
123         }
124     }
125 }
126
127
128 void help(void)
129 {
130     printf("usage: fft-test [-h] [-s] [-i] [-n b]\n"
131            "-h     print this help\n"
132            "-s     speed test\n"
133            "-m     (I)MDCT test\n"
134            "-i     inverse transform test\n"
135            "-n b   set the transform size to 2^b\n"
136            );
137     exit(1);
138 }
139
140
141
142 int main(int argc, char **argv)
143 {
144     FFTComplex *tab, *tab1, *tab_ref;
145     FFTSample *tabtmp, *tab2;
146     int it, i, c;
147     int do_speed = 0;
148     int do_mdct = 0;
149     int do_inverse = 0;
150     FFTContext s1, *s = &s1;
151     MDCTContext m1, *m = &m1;
152     int fft_nbits, fft_size;
153
154     mm_flags = 0;
155     fft_nbits = 9;
156     for(;;) {
157         c = getopt(argc, argv, "hsimn:");
158         if (c == -1)
159             break;
160         switch(c) {
161         case 'h':
162             help();
163             break;
164         case 's':
165             do_speed = 1;
166             break;
167         case 'i':
168             do_inverse = 1;
169             break;
170         case 'm':
171             do_mdct = 1;
172             break;
173         case 'n':
174             fft_nbits = atoi(optarg);
175             break;
176         }
177     }
178
179     fft_size = 1 << fft_nbits;
180     tab = av_malloc(fft_size * sizeof(FFTComplex));
181     tab1 = av_malloc(fft_size * sizeof(FFTComplex));
182     tab_ref = av_malloc(fft_size * sizeof(FFTComplex));
183     tabtmp = av_malloc(fft_size / 2 * sizeof(FFTSample));
184     tab2 = av_malloc(fft_size * sizeof(FFTSample));
185
186     if (do_mdct) {
187         if (do_inverse)
188             printf("IMDCT");
189         else
190             printf("MDCT");
191         ff_mdct_init(m, fft_nbits, do_inverse);
192     } else {
193         if (do_inverse)
194             printf("IFFT");
195         else
196             printf("FFT");
197         fft_init(s, fft_nbits, do_inverse);
198         fft_ref_init(fft_nbits, do_inverse);
199     }
200     printf(" %d test\n", fft_size);
201
202     /* generate random data */
203
204     for(i=0;i<fft_size;i++) {
205         tab1[i].re = frandom();
206         tab1[i].im = frandom();
207     }
208
209     /* checking result */
210     printf("Checking...\n");
211
212     if (do_mdct) {
213         if (do_inverse) {
214             imdct_ref((float *)tab_ref, (float *)tab1, fft_size);
215             ff_imdct_calc(m, tab2, (float *)tab1, tabtmp);
216             check_diff((float *)tab_ref, tab2, fft_size);
217         } else {
218             mdct_ref((float *)tab_ref, (float *)tab1, fft_size);
219             
220             ff_mdct_calc(m, tab2, (float *)tab1, tabtmp);
221
222             check_diff((float *)tab_ref, tab2, fft_size / 2);
223         }
224     } else {
225         memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
226         fft_permute(s, tab);
227         fft_calc(s, tab);
228         
229         fft_ref(tab_ref, tab1, fft_nbits);
230         check_diff((float *)tab_ref, (float *)tab, fft_size * 2);
231     }
232
233     /* do a speed test */
234
235     if (do_speed) {
236         INT64 time_start, duration;
237         int nb_its;
238
239         printf("Speed test...\n");
240         /* we measure during about 1 seconds */
241         nb_its = 1;
242         for(;;) {
243             time_start = gettime();
244             for(it=0;it<nb_its;it++) {
245                 if (do_mdct) {
246                     if (do_inverse) {
247                         ff_imdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
248                     } else {
249                         ff_mdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
250                     }
251                 } else {
252                     memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
253                     fft_calc(s, tab);
254                 }
255             }
256             duration = gettime() - time_start;
257             if (duration >= 1000000)
258                 break;
259             nb_its *= 2;
260         }
261         printf("time: %0.1f us/transform [total time=%0.2f s its=%d]\n", 
262                (double)duration / nb_its, 
263                (double)duration / 1000000.0,
264                nb_its);
265     }
266     
267     if (do_mdct) {
268         ff_mdct_end(m);
269     } else {
270         fft_end(s);
271     }
272     return 0;
273 }