1/*
2 * MDCT/IMDCT transforms
3 * Copyright (c) 2002 Fabrice Bellard
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdlib.h>
23#include <string.h>
24#include "libavutil/common.h"
25#include "libavutil/mathematics.h"
26#include "fft.h"
27#include "fft-internal.h"
28
29/**
30 * @file
31 * MDCT/IMDCT transforms.
32 */
33
34#if CONFIG_FFT_FLOAT
35#   define RSCALE(x) (x)
36#else
37#   define RSCALE(x) ((x) >> 1)
38#endif
39
40/**
41 * init MDCT or IMDCT computation.
42 */
43av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale)
44{
45    int n, n4, i;
46    double alpha, theta;
47    int tstep;
48
49    memset(s, 0, sizeof(*s));
50    n = 1 << nbits;
51    s->mdct_bits = nbits;
52    s->mdct_size = n;
53    n4 = n >> 2;
54    s->mdct_permutation = FF_MDCT_PERM_NONE;
55
56    if (ff_fft_init(s, s->mdct_bits - 2, inverse) < 0)
57        goto fail;
58
59    s->tcos = av_malloc(n/2 * sizeof(FFTSample));
60    if (!s->tcos)
61        goto fail;
62
63    switch (s->mdct_permutation) {
64    case FF_MDCT_PERM_NONE:
65        s->tsin = s->tcos + n4;
66        tstep = 1;
67        break;
68    case FF_MDCT_PERM_INTERLEAVE:
69        s->tsin = s->tcos + 1;
70        tstep = 2;
71        break;
72    default:
73        goto fail;
74    }
75
76    theta = 1.0 / 8.0 + (scale < 0 ? n4 : 0);
77    scale = sqrt(fabs(scale));
78    for(i=0;i<n4;i++) {
79        alpha = 2 * M_PI * (i + theta) / n;
80        s->tcos[i*tstep] = FIX15(-cos(alpha) * scale);
81        s->tsin[i*tstep] = FIX15(-sin(alpha) * scale);
82    }
83    return 0;
84 fail:
85    ff_mdct_end(s);
86    return -1;
87}
88
89/**
90 * Compute the middle half of the inverse MDCT of size N = 2^nbits,
91 * thus excluding the parts that can be derived by symmetry
92 * @param output N/2 samples
93 * @param input N/2 samples
94 */
95void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input)
96{
97    int k, n8, n4, n2, n, j;
98    const uint16_t *revtab = s->revtab;
99    const FFTSample *tcos = s->tcos;
100    const FFTSample *tsin = s->tsin;
101    const FFTSample *in1, *in2;
102    FFTComplex *z = (FFTComplex *)output;
103
104    n = 1 << s->mdct_bits;
105    n2 = n >> 1;
106    n4 = n >> 2;
107    n8 = n >> 3;
108
109    /* pre rotation */
110    in1 = input;
111    in2 = input + n2 - 1;
112    for(k = 0; k < n4; k++) {
113        j=revtab[k];
114        CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
115        in1 += 2;
116        in2 -= 2;
117    }
118    s->fft_calc(s, z);
119
120    /* post rotation + reordering */
121    for(k = 0; k < n8; k++) {
122        FFTSample r0, i0, r1, i1;
123        CMUL(r0, i1, z[n8-k-1].im, z[n8-k-1].re, tsin[n8-k-1], tcos[n8-k-1]);
124        CMUL(r1, i0, z[n8+k  ].im, z[n8+k  ].re, tsin[n8+k  ], tcos[n8+k  ]);
125        z[n8-k-1].re = r0;
126        z[n8-k-1].im = i0;
127        z[n8+k  ].re = r1;
128        z[n8+k  ].im = i1;
129    }
130}
131
132/**
133 * Compute inverse MDCT of size N = 2^nbits
134 * @param output N samples
135 * @param input N/2 samples
136 */
137void ff_imdct_calc_c(FFTContext *s, FFTSample *output, const FFTSample *input)
138{
139    int k;
140    int n = 1 << s->mdct_bits;
141    int n2 = n >> 1;
142    int n4 = n >> 2;
143
144    ff_imdct_half_c(s, output+n4, input);
145
146    for(k = 0; k < n4; k++) {
147        output[k] = -output[n2-k-1];
148        output[n-k-1] = output[n2+k];
149    }
150}
151
152/**
153 * Compute MDCT of size N = 2^nbits
154 * @param input N samples
155 * @param out N/2 samples
156 */
157void ff_mdct_calc_c(FFTContext *s, FFTSample *out, const FFTSample *input)
158{
159    int i, j, n, n8, n4, n2, n3;
160    FFTDouble re, im;
161    const uint16_t *revtab = s->revtab;
162    const FFTSample *tcos = s->tcos;
163    const FFTSample *tsin = s->tsin;
164    FFTComplex *x = (FFTComplex *)out;
165
166    n = 1 << s->mdct_bits;
167    n2 = n >> 1;
168    n4 = n >> 2;
169    n8 = n >> 3;
170    n3 = 3 * n4;
171
172    /* pre rotation */
173    for(i=0;i<n8;i++) {
174        re = RSCALE(-input[2*i+n3] - input[n3-1-2*i]);
175        im = RSCALE(-input[n4+2*i] + input[n4-1-2*i]);
176        j = revtab[i];
177        CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
178
179        re = RSCALE( input[2*i]    - input[n2-1-2*i]);
180        im = RSCALE(-input[n2+2*i] - input[ n-1-2*i]);
181        j = revtab[n8 + i];
182        CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
183    }
184
185    s->fft_calc(s, x);
186
187    /* post rotation */
188    for(i=0;i<n8;i++) {
189        FFTSample r0, i0, r1, i1;
190        CMUL(i1, r0, x[n8-i-1].re, x[n8-i-1].im, -tsin[n8-i-1], -tcos[n8-i-1]);
191        CMUL(i0, r1, x[n8+i  ].re, x[n8+i  ].im, -tsin[n8+i  ], -tcos[n8+i  ]);
192        x[n8-i-1].re = r0;
193        x[n8-i-1].im = i0;
194        x[n8+i  ].re = r1;
195        x[n8+i  ].im = i1;
196    }
197}
198
199av_cold void ff_mdct_end(FFTContext *s)
200{
201    av_freep(&s->tcos);
202    ff_fft_end(s);
203}
204