Merge pull request #226 from digitall/sincos

Replace large static Sin and Cos tables with dynamically generated ones.
This commit is contained in:
Filippos Karapetis 2012-04-19 01:13:47 -07:00
commit a1618c215b
10 changed files with 136 additions and 16528 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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];

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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