aboutsummaryrefslogtreecommitdiff
path: root/audio/decoders
diff options
context:
space:
mode:
authorD G Turner2012-04-12 19:03:36 +0100
committerD G Turner2012-04-13 07:37:30 +0100
commit7f930dfae33ded8d762c773bc8b3dca742607542 (patch)
tree2e831197bc114f25fbbfb31fa8d45d5eee994315 /audio/decoders
parentce1f805212ca1c2b56692f8ce02eed3f40f252f7 (diff)
downloadscummvm-rg350-7f930dfae33ded8d762c773bc8b3dca742607542.tar.gz
scummvm-rg350-7f930dfae33ded8d762c773bc8b3dca742607542.tar.bz2
scummvm-rg350-7f930dfae33ded8d762c773bc8b3dca742607542.zip
AUDIO: Migrate QDM2 Codec to using Common::RDFT class.
Diffstat (limited to 'audio/decoders')
-rw-r--r--audio/decoders/qdm2.cpp111
1 files changed, 6 insertions, 105 deletions
diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp
index a6315619d3..7476ae389e 100644
--- a/audio/decoders/qdm2.cpp
+++ b/audio/decoders/qdm2.cpp
@@ -35,6 +35,7 @@
#include "common/array.h"
#include "common/debug.h"
#include "common/math.h"
+#include "common/rdft.h"
#include "common/stream.h"
#include "common/memstream.h"
#include "common/bitstream.h"
@@ -100,13 +101,6 @@ struct QDM2FFT {
} PACKED_STRUCT;
#include "common/pack-end.h"
-enum RDFTransformType {
- RDFT,
- IRDFT,
- RIDFT,
- IRIDFT
-};
-
struct FFTComplex {
float re, im;
};
@@ -136,17 +130,6 @@ enum {
FF_MDCT_PERM_INTERLEAVE = 1
};
-struct RDFTContext {
- int nbits;
- int inverse;
- int signConvention;
-
- // pre/post rotation tables
- float *tcos;
- float *tsin;
- FFTContext fft;
-};
-
class QDM2Stream : public Codec {
public:
QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData);
@@ -190,7 +173,7 @@ private:
int _fftCoefsMinIndex[5];
int _fftCoefsMaxIndex[5];
int _fftLevelExp[6];
- RDFTContext _rdftCtx;
+ Common::RDFT *_rdft;
QDM2FFT _fft;
// I/O data
@@ -722,87 +705,6 @@ int fftInit(FFTContext *s, int nbits, int inverse) {
return -1;
}
-/**
- * Sets up a real FFT.
- * @param nbits log2 of the length of the input array
- * @param trans the type of transform
- */
-int rdftInit(RDFTContext *s, int nbits, RDFTransformType trans) {
- int n = 1 << nbits;
- const double theta = (trans == RDFT || trans == IRIDFT ? -1 : 1) * 2 * M_PI / n;
-
- s->nbits = nbits;
- s->inverse = trans == IRDFT || trans == IRIDFT;
- s->signConvention = trans == RIDFT || trans == IRIDFT ? 1 : -1;
-
- if (nbits < 4 || nbits > 16)
- return -1;
-
- if (fftInit(&s->fft, nbits - 1, trans == IRDFT || trans == RIDFT) < 0)
- return -1;
-
- initCosineTables(nbits);
- s->tcos = ff_cos_tabs[nbits];
- s->tsin = ff_sin_tabs[nbits] + (trans == RDFT || trans == IRIDFT) * (n >> 2);
-
- for (int i = 0; i < n >> 2; i++)
- s->tsin[i] = sin(i*theta);
-
- return 0;
-}
-
-/** Map one real FFT into two parallel real even and odd FFTs. Then interleave
- * the two real FFTs into one complex FFT. Unmangle the results.
- * ref: http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM
- */
-void rdftCalc(RDFTContext *s, float *data) {
- FFTComplex ev, od;
-
- const int n = 1 << s->nbits;
- const float k1 = 0.5;
- const float k2 = 0.5 - s->inverse;
- const float *tcos = s->tcos;
- const float *tsin = s->tsin;
-
- if (!s->inverse) {
- fftPermute(&s->fft, (FFTComplex *)data);
- fftCalc(&s->fft, (FFTComplex *)data);
- }
-
- // i=0 is a special case because of packing, the DC term is real, so we
- // are going to throw the N/2 term (also real) in with it.
- ev.re = data[0];
- data[0] = ev.re + data[1];
- data[1] = ev.re - data[1];
-
- int i;
-
- for (i = 1; i < n >> 2; i++) {
- int i1 = i * 2;
- int i2 = n - i1;
-
- // Separate even and odd FFTs
- ev.re = k1 * (data[i1] + data[i2]);
- od.im = -k2 * (data[i1] - data[i2]);
- ev.im = k1 * (data[i1 + 1] - data[i2 + 1]);
- od.re = k2 * (data[i1 + 1] + data[i2 + 1]);
-
- // Apply twiddle factors to the odd FFT and add to the even FFT
- data[i1] = ev.re + od.re * tcos[i] - od.im * tsin[i];
- data[i1 + 1] = ev.im + od.im * tcos[i] + od.re * tsin[i];
- data[i2] = ev.re - od.re * tcos[i] + od.im * tsin[i];
- data[i2 + 1] = -ev.im + od.im * tcos[i] + od.re * tsin[i];
- }
-
- data[i * 2 + 1] = s->signConvention * data[i * 2 + 1];
- if (s->inverse) {
- data[0] *= k1;
- data[1] *= k1;
- fftPermute(&s->fft, (FFTComplex *)data);
- fftCalc(&s->fft, (FFTComplex *)data);
- }
-}
-
// half mpeg encoding window (full precision)
const int32 ff_mpa_enwindow[257] = {
0, -1, -1, -1, -1, -1, -1, -2,
@@ -1755,7 +1657,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::F
if (_fftOrder < 7 || _fftOrder > 9)
error("QDM2Stream::QDM2Stream() Unsupported fft_order: %d", _fftOrder);
- rdftInit(&_rdftCtx, _fftOrder, IRDFT);
+ _rdft = new Common::RDFT(_fftOrder, Common::RDFT::IDFT_C2R);
initVlc();
ff_mpa_synth_init(ff_mpa_synth_window);
@@ -1770,6 +1672,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::F
}
QDM2Stream::~QDM2Stream() {
+ delete _rdft;
delete[] _compressedData;
}
@@ -2991,15 +2894,13 @@ void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) {
}
void QDM2Stream::qdm2_calculate_fft(int channel) {
- int i;
-
_fft.complex[channel][0].re *= 2.0f;
_fft.complex[channel][0].im = 0.0f;
- rdftCalc(&_rdftCtx, (float *)_fft.complex[channel]);
+ _rdft->calc((float *)_fft.complex[channel]);
// add samples to output buffer
- for (i = 0; i < ((_fftFrameSize + 15) & ~15); i++)
+ for (int i = 0; i < ((_fftFrameSize + 15) & ~15); i++)
_outputBuffer[_channels * i + channel] += ((float *) _fft.complex[channel])[i];
}