]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/fft-test.c
fft-test: Add RDFT/IRDFT support.
[ffmpeg] / libavcodec / fft-test.c
index 3e5da2f2b9c6d9bd13d31d9e66a165dc766bbe21..ed1b370a40795fcc5955f1997f4b922b81c09d47 100644 (file)
@@ -173,7 +173,11 @@ static void help(void)
     exit(1);
 }
 
-
+enum tf_transform {
+    TRANSFORM_FFT,
+    TRANSFORM_MDCT,
+    TRANSFORM_RDFT,
+};
 
 int main(int argc, char **argv)
 {
@@ -181,18 +185,19 @@ int main(int argc, char **argv)
     FFTSample *tab2;
     int it, i, c;
     int do_speed = 0;
-    int do_mdct = 0;
+    enum tf_transform transform = TRANSFORM_FFT;
     int do_inverse = 0;
     FFTContext s1, *s = &s1;
     FFTContext m1, *m = &m1;
-    int fft_nbits, fft_size;
+    RDFTContext r1, *r = &r1;
+    int fft_nbits, fft_size, fft_size_2;
     double scale = 1.0;
     AVLFG prng;
     av_lfg_init(&prng, 1);
 
     fft_nbits = 9;
     for(;;) {
-        c = getopt(argc, argv, "hsimn:f:");
+        c = getopt(argc, argv, "hsimrn:f:");
         if (c == -1)
             break;
         switch(c) {
@@ -206,7 +211,10 @@ int main(int argc, char **argv)
             do_inverse = 1;
             break;
         case 'm':
-            do_mdct = 1;
+            transform = TRANSFORM_MDCT;
+            break;
+        case 'r':
+            transform = TRANSFORM_RDFT;
             break;
         case 'n':
             fft_nbits = atoi(optarg);
@@ -218,25 +226,37 @@ int main(int argc, char **argv)
     }
 
     fft_size = 1 << fft_nbits;
+    fft_size_2 = fft_size >> 1;
     tab = av_malloc(fft_size * sizeof(FFTComplex));
     tab1 = av_malloc(fft_size * sizeof(FFTComplex));
     tab_ref = av_malloc(fft_size * sizeof(FFTComplex));
     tab2 = av_malloc(fft_size * sizeof(FFTSample));
 
-    if (do_mdct) {
+    switch (transform) {
+    case TRANSFORM_MDCT:
         av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale);
         if (do_inverse)
             av_log(NULL, AV_LOG_INFO,"IMDCT");
         else
             av_log(NULL, AV_LOG_INFO,"MDCT");
         ff_mdct_init(m, fft_nbits, do_inverse, scale);
-    } else {
+        break;
+    case TRANSFORM_FFT:
         if (do_inverse)
             av_log(NULL, AV_LOG_INFO,"IFFT");
         else
             av_log(NULL, AV_LOG_INFO,"FFT");
         ff_fft_init(s, fft_nbits, do_inverse);
         fft_ref_init(fft_nbits, do_inverse);
+        break;
+    case TRANSFORM_RDFT:
+        if (do_inverse)
+            av_log(NULL, AV_LOG_INFO,"IRDFT");
+        else
+            av_log(NULL, AV_LOG_INFO,"RDFT");
+        ff_rdft_init(r, fft_nbits, do_inverse ? IRDFT : RDFT);
+        fft_ref_init(fft_nbits, do_inverse);
+        break;
     }
     av_log(NULL, AV_LOG_INFO," %d test\n", fft_size);
 
@@ -250,7 +270,8 @@ int main(int argc, char **argv)
     /* checking result */
     av_log(NULL, AV_LOG_INFO,"Checking...\n");
 
-    if (do_mdct) {
+    switch (transform) {
+    case TRANSFORM_MDCT:
         if (do_inverse) {
             imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits);
             ff_imdct_calc(m, tab2, (float *)tab1);
@@ -262,13 +283,44 @@ int main(int argc, char **argv)
 
             check_diff((float *)tab_ref, tab2, fft_size / 2, scale);
         }
-    } else {
+        break;
+    case TRANSFORM_FFT:
         memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
         ff_fft_permute(s, tab);
         ff_fft_calc(s, tab);
 
         fft_ref(tab_ref, tab1, fft_nbits);
         check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 1.0);
+        break;
+    case TRANSFORM_RDFT:
+        if (do_inverse) {
+            tab1[         0].im = 0;
+            tab1[fft_size_2].im = 0;
+            for (i = 1; i < fft_size_2; i++) {
+                tab1[fft_size_2+i].re =  tab1[fft_size_2-i].re;
+                tab1[fft_size_2+i].im = -tab1[fft_size_2-i].im;
+            }
+
+            memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
+            tab2[1] = tab1[fft_size_2].re;
+
+            ff_rdft_calc(r, tab2);
+            fft_ref(tab_ref, tab1, fft_nbits);
+            for (i = 0; i < fft_size; i++) {
+                tab[i].re = tab2[i];
+                tab[i].im = 0;
+            }
+            check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 0.5);
+        } else {
+            for (i = 0; i < fft_size; i++) {
+                tab2[i]    = tab1[i].re;
+                tab1[i].im = 0;
+            }
+            ff_rdft_calc(r, tab2);
+            fft_ref(tab_ref, tab1, fft_nbits);
+            tab_ref[0].im = tab_ref[fft_size_2].re;
+            check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0);
+        }
     }
 
     /* do a speed test */
@@ -283,15 +335,22 @@ int main(int argc, char **argv)
         for(;;) {
             time_start = gettime();
             for (it = 0; it < nb_its; it++) {
-                if (do_mdct) {
+                switch (transform) {
+                case TRANSFORM_MDCT:
                     if (do_inverse) {
                         ff_imdct_calc(m, (float *)tab, (float *)tab1);
                     } else {
                         ff_mdct_calc(m, (float *)tab, (float *)tab1);
                     }
-                } else {
+                    break;
+                case TRANSFORM_FFT:
                     memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
                     ff_fft_calc(s, tab);
+                    break;
+                case TRANSFORM_RDFT:
+                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
+                    ff_rdft_calc(r, tab2);
+                    break;
                 }
             }
             duration = gettime() - time_start;
@@ -305,10 +364,16 @@ int main(int argc, char **argv)
                nb_its);
     }
 
-    if (do_mdct) {
+    switch (transform) {
+    case TRANSFORM_MDCT:
         ff_mdct_end(m);
-    } else {
+        break;
+    case TRANSFORM_FFT:
         ff_fft_end(s);
+        break;
+    case TRANSFORM_RDFT:
+        ff_rdft_end(r);
+        break;
     }
     return 0;
 }