xoreos  0.0.5
mdct.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* Based on the (I)MDCT code in FFmpeg (<https://ffmpeg.org/)>, which
26  * is released under the terms of version 2 or later of the GNU Lesser
27  * General Public License.
28  *
29  * The original copyright note in libavcodec/mdct_template.c reads as follows:
30  *
31  * MDCT/IMDCT transforms
32  * Copyright (c) 2002 Fabrice Bellard
33  *
34  * This file is part of FFmpeg.
35  *
36  * FFmpeg is free software; you can redistribute it and/or
37  * modify it under the terms of the GNU Lesser General Public
38  * License as published by the Free Software Foundation; either
39  * version 2.1 of the License, or (at your option) any later version.
40  *
41  * FFmpeg is distributed in the hope that it will be useful,
42  * but WITHOUT ANY WARRANTY; without even the implied warranty of
43  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44  * Lesser General Public License for more details.
45  *
46  * You should have received a copy of the GNU Lesser General Public
47  * License along with FFmpeg; if not, write to the Free Software
48  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49  */
50 
51 #include "src/common/maths.h"
52 #include "src/common/util.h"
53 #include "src/common/fft.h"
54 #include "src/common/mdct.h"
55 
56 namespace Common {
57 
58 MDCT::MDCT(int bits, bool inverse, double scale) : _bits(bits) {
59  _size = 1 << bits;
60 
61  _fft.reset(new FFT(_bits - 2, inverse));
62 
63  const int size2 = _size >> 1;
64  const int size4 = _size >> 2;
65 
66  _tCos.reset(new float[size2]);
67  _tSin = _tCos.get() + size4;
68 
69  const double theta = 1.0 / 8.0 + (scale < 0 ? size4 : 0);
70 
71  scale = sqrt(ABS(scale));
72  for (int i = 0; i < size4; i++) {
73  const double alpha = 2 * M_PI * (i + theta) / _size;
74 
75  _tCos[i] = -cos(alpha) * scale;
76  _tSin[i] = -sin(alpha) * scale;
77  }
78 }
79 
81 }
82 
83 #define CMUL(dre, dim, are, aim, bre, bim) do { \
84  (dre) = (are) * (bre) - (aim) * (bim); \
85  (dim) = (are) * (bim) + (aim) * (bre); \
86  } while (0)
87 
88 void MDCT::calcMDCT(float *output, const float *input) {
89  Complex *x = reinterpret_cast<Complex *>(output);
90 
91  const int size2 = _size >> 1;
92  const int size4 = _size >> 2;
93  const int size8 = _size >> 3;
94  const int size3 = _size * 3;
95 
96  const uint16 *revTab = _fft->getRevTab();
97 
98  // Pre rotation
99  for (int i = 0; i < size8; i++) {
100  float re = -input[2 * i + size3] - input[size3 - 1 - 2 * i];
101  float im = -input[2 * i + size4] + input[size4 - 1 - 2 * i];
102  int j = revTab[i];
103 
104  CMUL(x[j].re, x[j].im, re, im, -_tCos[i], _tSin[i]);
105 
106  re = input[2 * i ] - input[size2 - 1 - 2 * i];
107  im = -input[2 * i + size2] - input[_size - 1 - 2 * i];
108  j = revTab[size8 + i];
109 
110  CMUL(x[j].re, x[j].im, re, im, -_tCos[size8 + i], _tSin[size8 + i]);
111  }
112 
113  _fft->calc(x);
114 
115  // Post rotation
116  for (int i = 0; i < size8; i++) {
117  float r0, i0, r1, i1;
118 
119  CMUL(i1, r0, x[size8-i-1].re, x[size8-i-1].im, -_tSin[size8-i-1], -_tCos[size8-i-1]);
120  CMUL(i0, r1, x[size8+i ].re, x[size8+i ].im, -_tSin[size8+i ], -_tCos[size8+i ]);
121 
122  x[size8 - i - 1].re = r0;
123  x[size8 - i - 1].im = i0;
124  x[size8 + i ].re = r1;
125  x[size8 + i ].im = i1;
126  }
127 }
128 
129 void MDCT::calcIMDCT(float *output, const float *input) {
130  const int size2 = _size >> 1;
131  const int size4 = _size >> 2;
132 
133  calcHalfIMDCT(output + size4, input);
134 
135  for (int k = 0; k < size4; k++) {
136  output[ k ] = -output[size2 - k - 1];
137  output[_size - k - 1] = output[size2 + k ];
138  }
139 }
140 
141 void MDCT::calcHalfIMDCT(float *output, const float *input) {
142  Complex *z = reinterpret_cast<Complex *>(output);
143 
144  const int size2 = _size >> 1;
145  const int size4 = _size >> 2;
146  const int size8 = _size >> 3;
147 
148  const uint16 *revTab = _fft->getRevTab();
149 
150  // Pre rotation
151  const float *in1 = input;
152  const float *in2 = input + size2 - 1;
153  for (int k = 0; k < size4; k++) {
154  const int j = revTab[k];
155 
156  CMUL(z[j].re, z[j].im, *in2, *in1, _tCos[k], _tSin[k]);
157 
158  in1 += 2;
159  in2 -= 2;
160  }
161 
162  _fft->calc(z);
163 
164  // Post rotation + reordering
165  for (int k = 0; k < size8; k++) {
166  float r0, i0, r1, i1;
167 
168  CMUL(r0, i1, z[size8-k-1].im, z[size8-k-1].re, _tSin[size8-k-1], _tCos[size8-k-1]);
169  CMUL(r1, i0, z[size8+k ].im, z[size8+k ].re, _tSin[size8+k ], _tCos[size8+k ]);
170 
171  z[size8 - k - 1].re = r0;
172  z[size8 - k - 1].im = i0;
173  z[size8 + k ].re = r1;
174  z[size8 + k ].im = i1;
175  }
176 }
177 
178 } // End of namespace Common
(Inverse) Modified Discrete Cosine Transforms.
T ABS(T x)
Definition: util.h:69
A complex number.
Definition: maths.h:61
Definition: 2dafile.h:39
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
float im
Definition: maths.h:62
Mathematical helpers.
#define M_PI
Definition: maths.h:39
ScopedPtr< FFT > _fft
Definition: mdct.h:82
void calcHalfIMDCT(float *output, const float *input)
Compute the middle half of the inverse MDCT of size N = 2^nbits, thus excluding the parts that can be...
Definition: mdct.cpp:141
int _size
Definition: mdct.h:77
float * _tSin
Definition: mdct.h:80
uint16_t uint16
Definition: types.h:202
Utility templates and functions.
ScopedArray< float > _tCos
Definition: mdct.h:79
float re
Definition: maths.h:62
#define CMUL(dre, dim, are, aim, bre, bim)
Definition: mdct.cpp:83
void calcIMDCT(float *output, const float *input)
Compute inverse MDCT of size N = 2^nbits.
Definition: mdct.cpp:129
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
static glm::mat4 inverse(const glm::mat4 &m)
Definition: graphics.cpp:1363
(Inverse) Fast Fourier Transform.
Definition: fft.h:66
int _bits
Definition: mdct.h:76
(Inverse) Fast Fourier Transform.
void calcMDCT(float *output, const float *input)
Compute MDCT of size N = 2^nbits.
Definition: mdct.cpp:88
MDCT(int bits, bool inverse, double scale)
Definition: mdct.cpp:58