Browse code

Fixed-point support in fft-test

Signed-off-by: Mans Rullgard <mans@mansr.com>

Mans Rullgard authored on 2011/03/31 05:13:21
Showing 3 changed files
... ...
@@ -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);