Browse code

Fixed-point MDCT with 32-bit unscaled output

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

Mans Rullgard authored on 2011/03/22 02:52:34
Showing 4 changed files
... ...
@@ -39,6 +39,8 @@
39 39
 #include "libavutil/intmath.h"
40 40
 #include "mathops.h"
41 41
 
42
+void ff_mdct_calcw_c(FFTContext *s, FFTDouble *output, const FFTSample *input);
43
+
42 44
 #define SCALE_FLOAT(a, bits) lrint((a) * (double)(1 << (bits)))
43 45
 #define FIX15(a) av_clip(SCALE_FLOAT(a, 15), -32767, 32767)
44 46
 
... ...
@@ -49,11 +51,17 @@
49 49
         y = (a + b) >> 1;                       \
50 50
     } while (0)
51 51
 
52
-#define CMUL(dre, dim, are, aim, bre, bim) do {                 \
53
-        (dre) = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;      \
54
-        (dim) = (MUL16(are, bim) + MUL16(aim, bre)) >> 15;      \
52
+#define CMULS(dre, dim, are, aim, bre, bim, sh) do {            \
53
+        (dre) = (MUL16(are, bre) - MUL16(aim, bim)) >> sh;      \
54
+        (dim) = (MUL16(are, bim) + MUL16(aim, bre)) >> sh;      \
55 55
     } while (0)
56 56
 
57
+#define CMUL(dre, dim, are, aim, bre, bim)      \
58
+    CMULS(dre, dim, are, aim, bre, bim, 15)
59
+
60
+#define CMULL(dre, dim, are, aim, bre, bim)     \
61
+    CMULS(dre, dim, are, aim, bre, bim, 0)
62
+
57 63
 #endif /* CONFIG_FFT_FLOAT */
58 64
 
59 65
 #define ff_imdct_calc_c FFT_NAME(ff_imdct_calc_c)
... ...
@@ -123,6 +123,9 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
123 123
     if (ARCH_ARM)     ff_fft_init_arm(s);
124 124
     if (HAVE_ALTIVEC) ff_fft_init_altivec(s);
125 125
     if (HAVE_MMX)     ff_fft_init_mmx(s);
126
+    if (CONFIG_MDCT)  s->mdct_calcw = s->mdct_calc;
127
+#else
128
+    if (CONFIG_MDCT)  s->mdct_calcw = ff_mdct_calcw_c;
126 129
 #endif
127 130
 
128 131
     for(j=4; j<=nbits; j++) {
... ...
@@ -53,6 +53,10 @@ typedef struct FFTContext FFTContext;
53 53
 
54 54
 #endif /* CONFIG_FFT_FLOAT */
55 55
 
56
+typedef struct FFTDComplex {
57
+    FFTDouble re, im;
58
+} FFTDComplex;
59
+
56 60
 /* FFT computation */
57 61
 
58 62
 struct FFTContext {
... ...
@@ -77,6 +81,7 @@ struct FFTContext {
77 77
     void (*imdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input);
78 78
     void (*imdct_half)(struct FFTContext *s, FFTSample *output, const FFTSample *input);
79 79
     void (*mdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input);
80
+    void (*mdct_calcw)(struct FFTContext *s, FFTDouble *output, const FFTSample *input);
80 81
     int fft_permutation;
81 82
 #define FF_FFT_PERM_DEFAULT   0
82 83
 #define FF_FFT_PERM_SWAP_LSBS 1
... ...
@@ -18,3 +18,47 @@
18 18
 
19 19
 #define CONFIG_FFT_FLOAT 0
20 20
 #include "mdct.c"
21
+
22
+/* same as ff_mdct_calcw_c with double-width unscaled output */
23
+void ff_mdct_calcw_c(FFTContext *s, FFTDouble *out, const FFTSample *input)
24
+{
25
+    int i, j, n, n8, n4, n2, n3;
26
+    FFTDouble re, im;
27
+    const uint16_t *revtab = s->revtab;
28
+    const FFTSample *tcos = s->tcos;
29
+    const FFTSample *tsin = s->tsin;
30
+    FFTComplex *x = s->tmp_buf;
31
+    FFTDComplex *o = (FFTDComplex *)out;
32
+
33
+    n = 1 << s->mdct_bits;
34
+    n2 = n >> 1;
35
+    n4 = n >> 2;
36
+    n8 = n >> 3;
37
+    n3 = 3 * n4;
38
+
39
+    /* pre rotation */
40
+    for(i=0;i<n8;i++) {
41
+        re = RSCALE(-input[2*i+n3] - input[n3-1-2*i]);
42
+        im = RSCALE(-input[n4+2*i] + input[n4-1-2*i]);
43
+        j = revtab[i];
44
+        CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
45
+
46
+        re = RSCALE( input[2*i]    - input[n2-1-2*i]);
47
+        im = RSCALE(-input[n2+2*i] - input[ n-1-2*i]);
48
+        j = revtab[n8 + i];
49
+        CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
50
+    }
51
+
52
+    s->fft_calc(s, x);
53
+
54
+    /* post rotation */
55
+    for(i=0;i<n8;i++) {
56
+        FFTDouble r0, i0, r1, i1;
57
+        CMULL(i1, r0, x[n8-i-1].re, x[n8-i-1].im, -tsin[n8-i-1], -tcos[n8-i-1]);
58
+        CMULL(i0, r1, x[n8+i  ].re, x[n8+i  ].im, -tsin[n8+i  ], -tcos[n8+i  ]);
59
+        o[n8-i-1].re = r0;
60
+        o[n8-i-1].im = i0;
61
+        o[n8+i  ].re = r1;
62
+        o[n8+i  ].im = i1;
63
+    }
64
+}