mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-20 19:21:46 +00:00
Merge pull request #226 from digitall/sincos
Replace large static Sin and Cos tables with dynamically generated ones.
This commit is contained in:
commit
a1618c215b
File diff suppressed because it is too large
Load Diff
@ -25,12 +25,30 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
* Get a cosine table with the specified bit precision
|
||||
*
|
||||
* @param bits Precision of the table, which must be in range [4, 16]
|
||||
*/
|
||||
const float *getCosineTable(int bits);
|
||||
class CosineTable {
|
||||
public:
|
||||
/**
|
||||
* Construct a cosine table with the specified bit precision
|
||||
*
|
||||
* @param bitPrecision Precision of the table, which must be in range [4, 16]
|
||||
*/
|
||||
CosineTable(int bitPrecision);
|
||||
~CosineTable();
|
||||
|
||||
/**
|
||||
* Get pointer to table
|
||||
*/
|
||||
const float *getTable() { return _table; }
|
||||
|
||||
/**
|
||||
* Get pointer to table
|
||||
*/
|
||||
int getPrecision() { return _bitPrecision; }
|
||||
|
||||
private:
|
||||
float *_table;
|
||||
int _bitPrecision;
|
||||
};
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
|
@ -26,15 +26,14 @@
|
||||
// Copyright (c) 2010 Alex Converse <alex.converse@gmail.com>
|
||||
// Copyright (c) 2010 Vitor Sessak
|
||||
|
||||
#include "common/cosinetables.h"
|
||||
#include "common/dct.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
DCT::DCT(int bits, TransformType trans) : _bits(bits), _trans(trans), _rdft(0) {
|
||||
DCT::DCT(int bits, TransformType trans) : _bits(bits), _cos(_bits + 2), _trans(trans), _rdft(0) {
|
||||
int n = 1 << _bits;
|
||||
|
||||
_tCos = getCosineTable(_bits + 2);
|
||||
_tCos = _cos.getTable();
|
||||
|
||||
_csc2 = new float[n / 2];
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "common/math.h"
|
||||
#include "common/rdft.h"
|
||||
|
||||
#include "common/cosinetables.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
@ -59,6 +61,7 @@ private:
|
||||
int _bits;
|
||||
TransformType _trans;
|
||||
|
||||
CosineTable _cos;
|
||||
const float *_tCos;
|
||||
|
||||
float *_csc2;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "common/cosinetables.h"
|
||||
#include "common/fft.h"
|
||||
#include "common/util.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
@ -45,6 +46,13 @@ FFT::FFT(int bits, int inverse) : _bits(bits), _inverse(inverse) {
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
_revTab[-splitRadixPermutation(i, n, _inverse) & (n - 1)] = i;
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_cosTables); i++) {
|
||||
if (i+4 <= _bits)
|
||||
_cosTables[i] = new Common::CosineTable(i+4);
|
||||
else
|
||||
_cosTables[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FFT::~FFT() {
|
||||
@ -162,15 +170,7 @@ PASS(pass)
|
||||
#define BUTTERFLIES BUTTERFLIES_BIG
|
||||
PASS(pass_big)
|
||||
|
||||
#define DECL_FFT(t, n, n2, n4) \
|
||||
static void fft##n(Complex *z) { \
|
||||
fft##n2(z); \
|
||||
fft##n4(z + n4 * 2); \
|
||||
fft##n4(z + n4 * 3); \
|
||||
pass(z, getCosineTable(t), n4 / 2);\
|
||||
}
|
||||
|
||||
static void fft4(Complex *z) {
|
||||
void FFT::fft4(Complex *z) {
|
||||
float t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
BF(t3, t1, z[0].re, z[1].re);
|
||||
@ -183,7 +183,7 @@ static void fft4(Complex *z) {
|
||||
BF(z[2].im, z[0].im, t2, t5);
|
||||
}
|
||||
|
||||
static void fft8(Complex *z) {
|
||||
void FFT::fft8(Complex *z) {
|
||||
float t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
fft4(z);
|
||||
@ -202,14 +202,15 @@ static void fft8(Complex *z) {
|
||||
TRANSFORM(z[1], z[3], z[5], z[7], sqrthalf, sqrthalf);
|
||||
}
|
||||
|
||||
static void fft16(Complex *z) {
|
||||
void FFT::fft16(Complex *z) {
|
||||
float t1, t2, t3, t4, t5, t6;
|
||||
|
||||
fft8(z);
|
||||
fft4(z + 8);
|
||||
fft4(z + 12);
|
||||
|
||||
const float * const cosTable = getCosineTable(4);
|
||||
assert(_cosTables[0]);
|
||||
const float * const cosTable = _cosTables[0]->getTable();
|
||||
|
||||
TRANSFORM_ZERO(z[0], z[4], z[8], z[12]);
|
||||
TRANSFORM(z[2], z[6], z[10], z[14], sqrthalf, sqrthalf);
|
||||
@ -217,27 +218,31 @@ static void fft16(Complex *z) {
|
||||
TRANSFORM(z[3], z[7], z[11], z[15], cosTable[3], cosTable[1]);
|
||||
}
|
||||
|
||||
DECL_FFT(5, 32, 16, 8)
|
||||
DECL_FFT(6, 64, 32, 16)
|
||||
DECL_FFT(7, 128, 64, 32)
|
||||
DECL_FFT(8, 256, 128, 64)
|
||||
DECL_FFT(9, 512, 256, 128)
|
||||
#define pass pass_big
|
||||
DECL_FFT(10, 1024, 512, 256)
|
||||
DECL_FFT(11, 2048, 1024, 512)
|
||||
DECL_FFT(12, 4096, 2048, 1024)
|
||||
DECL_FFT(13, 8192, 4096, 2048)
|
||||
DECL_FFT(14, 16384, 8192, 4096)
|
||||
DECL_FFT(15, 32768, 16384, 8192)
|
||||
DECL_FFT(16, 65536, 32768, 16384)
|
||||
|
||||
static void (* const fft_dispatch[])(Complex *) = {
|
||||
fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
|
||||
fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
|
||||
};
|
||||
void FFT::fft(int n, int logn, Complex *z) {
|
||||
switch (logn) {
|
||||
case 2:
|
||||
fft4(z);
|
||||
break;
|
||||
case 3:
|
||||
fft8(z);
|
||||
break;
|
||||
case 4:
|
||||
fft16(z);
|
||||
break;
|
||||
default:
|
||||
fft((n / 2), logn - 1, z);
|
||||
fft((n / 4), logn - 2, z + (n / 4) * 2);
|
||||
fft((n / 4), logn - 2, z + (n / 4) * 3);
|
||||
assert(_cosTables[logn - 4]);
|
||||
if (n > 1024)
|
||||
pass_big(z, _cosTables[logn - 4]->getTable(), (n / 4) / 2);
|
||||
else
|
||||
pass(z, _cosTables[logn - 4]->getTable(), (n / 4) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void FFT::calc(Complex *z) {
|
||||
fft_dispatch[_bits - 2](z);
|
||||
fft(1 << _bits, _bits, z);
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
||||
|
12
common/fft.h
12
common/fft.h
@ -34,6 +34,8 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
class CosineTable;
|
||||
|
||||
/**
|
||||
* (Inverse) Fast Fourier Transform.
|
||||
*
|
||||
@ -64,13 +66,17 @@ private:
|
||||
Complex *_expTab;
|
||||
Complex *_tmpBuf;
|
||||
|
||||
const float *_tSin;
|
||||
const float *_tCos;
|
||||
|
||||
int _splitRadix;
|
||||
int _permutation;
|
||||
|
||||
static int splitRadixPermutation(int i, int n, int inverse);
|
||||
|
||||
CosineTable *_cosTables[13];
|
||||
|
||||
void fft4(Complex *z);
|
||||
void fft8(Complex *z);
|
||||
void fft16(Complex *z);
|
||||
void fft(int n, int logn, Complex *z);
|
||||
};
|
||||
|
||||
} // End of namespace Common
|
||||
|
@ -25,12 +25,10 @@
|
||||
// Copyright (c) 2009 Alex Converse <alex dot converse at gmail dot com>
|
||||
|
||||
#include "common/rdft.h"
|
||||
#include "common/cosinetables.h"
|
||||
#include "common/sinetables.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _fft(0) {
|
||||
RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _sin(bits), _cos(bits), _fft(0) {
|
||||
assert ((_bits >= 4) && (_bits <= 16));
|
||||
|
||||
_inverse = trans == IDFT_C2R || trans == DFT_C2R;
|
||||
@ -40,8 +38,8 @@ RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _fft(0) {
|
||||
|
||||
int n = 1 << bits;
|
||||
|
||||
_tSin = getSineTable(bits) + (trans == DFT_R2C || trans == DFT_C2R) * (n >> 2);
|
||||
_tCos = getCosineTable(bits);
|
||||
_tSin = _sin.getTable() + (trans == DFT_R2C || trans == DFT_C2R) * (n >> 2);
|
||||
_tCos = _cos.getTable();
|
||||
}
|
||||
|
||||
RDFT::~RDFT() {
|
||||
|
@ -31,6 +31,9 @@
|
||||
#include "common/math.h"
|
||||
#include "common/fft.h"
|
||||
|
||||
#include "common/cosinetables.h"
|
||||
#include "common/sinetables.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
@ -62,6 +65,8 @@ private:
|
||||
int _inverse;
|
||||
int _signConvention;
|
||||
|
||||
SineTable _sin;
|
||||
CosineTable _cos;
|
||||
const float *_tSin;
|
||||
const float *_tCos;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,12 +25,30 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
* Get a sine table with the specified bit precision
|
||||
*
|
||||
* @param bits Precision of the table, which must be in range [4, 16]
|
||||
*/
|
||||
const float *getSineTable(int bits);
|
||||
class SineTable {
|
||||
public:
|
||||
/**
|
||||
* Construct a sine table with the specified bit precision
|
||||
*
|
||||
* @param bitPrecision Precision of the table, which must be in range [4, 16]
|
||||
*/
|
||||
SineTable(int bitPrecision);
|
||||
~SineTable();
|
||||
|
||||
/**
|
||||
* Get pointer to table
|
||||
*/
|
||||
const float *getTable() { return _table; }
|
||||
|
||||
/**
|
||||
* Get pointer to table
|
||||
*/
|
||||
int getPrecision() { return _bitPrecision; }
|
||||
|
||||
private:
|
||||
float *_table;
|
||||
int _bitPrecision;
|
||||
};
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user