aboutsummaryrefslogtreecommitdiff
path: root/audio/decoders
diff options
context:
space:
mode:
Diffstat (limited to 'audio/decoders')
-rw-r--r--audio/decoders/adpcm.cpp32
-rw-r--r--audio/decoders/adpcm_intern.h22
-rw-r--r--audio/decoders/aiff.h1
-rw-r--r--audio/decoders/qdm2.cpp880
-rw-r--r--audio/decoders/quicktime.cpp64
-rw-r--r--audio/decoders/quicktime.h1
-rw-r--r--audio/decoders/quicktime_intern.h4
-rw-r--r--audio/decoders/voc.cpp14
8 files changed, 228 insertions, 790 deletions
diff --git a/audio/decoders/adpcm.cpp b/audio/decoders/adpcm.cpp
index 535652a0b3..2fe509e1f3 100644
--- a/audio/decoders/adpcm.cpp
+++ b/audio/decoders/adpcm.cpp
@@ -71,13 +71,19 @@ int Oki_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
- assert(numSamples % 2 == 0);
+ for (samples = 0; samples < numSamples && !endOfData(); samples++) {
+ if (_decodedSampleCount == 0) {
+ data = _stream->readByte();
+ _decodedSamples[0] = decodeOKI((data >> 4) & 0x0f);
+ _decodedSamples[1] = decodeOKI((data >> 0) & 0x0f);
+ _decodedSampleCount = 2;
+ }
- for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- buffer[samples] = decodeOKI((data >> 4) & 0x0f);
- buffer[samples + 1] = decodeOKI(data & 0x0f);
+ // (1 - (count - 1)) ensures that _decodedSamples acts as a FIFO of depth 2
+ buffer[samples] = _decodedSamples[1 - (_decodedSampleCount - 1)];
+ _decodedSampleCount--;
}
+
return samples;
}
@@ -117,13 +123,19 @@ int DVI_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
- assert(numSamples % 2 == 0);
+ for (samples = 0; samples < numSamples && !endOfData(); samples++) {
+ if (_decodedSampleCount == 0) {
+ data = _stream->readByte();
+ _decodedSamples[0] = decodeIMA((data >> 4) & 0x0f, 0);
+ _decodedSamples[1] = decodeIMA((data >> 0) & 0x0f, _channels == 2 ? 1 : 0);
+ _decodedSampleCount = 2;
+ }
- for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- buffer[samples] = decodeIMA((data >> 4) & 0x0f);
- buffer[samples + 1] = decodeIMA(data & 0x0f, _channels == 2 ? 1 : 0);
+ // (1 - (count - 1)) ensures that _decodedSamples acts as a FIFO of depth 2
+ buffer[samples] = _decodedSamples[1 - (_decodedSampleCount - 1)];
+ _decodedSampleCount--;
}
+
return samples;
}
diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h
index 31747aabaf..3b8d8c74d0 100644
--- a/audio/decoders/adpcm_intern.h
+++ b/audio/decoders/adpcm_intern.h
@@ -37,7 +37,6 @@
#include "common/stream.h"
#include "common/textconsole.h"
-
namespace Audio {
class ADPCMStream : public RewindableAudioStream {
@@ -64,12 +63,11 @@ public:
ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
- virtual bool isStereo() const { return _channels == 2; }
- virtual int getRate() const { return _rate; }
+ virtual bool isStereo() const { return _channels == 2; }
+ virtual int getRate() const { return _rate; }
virtual bool rewind();
-
/**
* This table is used by some ADPCM variants (IMA and OKI) to adjust the
* step for use on the next sample.
@@ -83,12 +81,18 @@ public:
class Oki_ADPCMStream : public ADPCMStream {
public:
Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+ : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
+
+ virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
virtual int readBuffer(int16 *buffer, const int numSamples);
protected:
int16 decodeOKI(byte);
+
+private:
+ uint8 _decodedSampleCount;
+ int16 _decodedSamples[2];
};
class Ima_ADPCMStream : public ADPCMStream {
@@ -108,9 +112,15 @@ public:
class DVI_ADPCMStream : public Ima_ADPCMStream {
public:
DVI_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
+ : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
+
+ virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
virtual int readBuffer(int16 *buffer, const int numSamples);
+
+private:
+ uint8 _decodedSampleCount;
+ int16 _decodedSamples[2];
};
class Apple_ADPCMStream : public Ima_ADPCMStream {
diff --git a/audio/decoders/aiff.h b/audio/decoders/aiff.h
index 59664bb85a..afcdb6ae6c 100644
--- a/audio/decoders/aiff.h
+++ b/audio/decoders/aiff.h
@@ -23,6 +23,7 @@
/**
* @file
* Sound decoder used in engines:
+ * - pegasus
* - saga
* - sci
* - sword1
diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp
index 2de7a68dd9..732de311aa 100644
--- a/audio/decoders/qdm2.cpp
+++ b/audio/decoders/qdm2.cpp
@@ -35,7 +35,10 @@
#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"
#include "common/textconsole.h"
namespace Audio {
@@ -50,14 +53,6 @@ enum {
typedef int8 sb_int8_array[2][30][64];
-/* bit input */
-/* buffer, buffer_end and size_in_bits must be present and used by every reader */
-struct GetBitContext {
- const uint8 *buffer, *bufferEnd;
- int index;
- int sizeInBits;
-};
-
struct QDM2SubPacket {
int type;
unsigned int size;
@@ -106,53 +101,6 @@ struct QDM2FFT {
} PACKED_STRUCT;
#include "common/pack-end.h"
-enum RDFTransformType {
- RDFT,
- IRDFT,
- RIDFT,
- IRIDFT
-};
-
-struct FFTComplex {
- float re, im;
-};
-
-struct FFTContext {
- int nbits;
- int inverse;
- uint16 *revtab;
- FFTComplex *exptab;
- FFTComplex *tmpBuf;
- int mdctSize; // size of MDCT (i.e. number of input data * 2)
- int mdctBits; // n = 2^nbits
- // pre/post rotation tables
- float *tcos;
- float *tsin;
- void (*fftPermute)(struct FFTContext *s, FFTComplex *z);
- void (*fftCalc)(struct FFTContext *s, FFTComplex *z);
- void (*imdctCalc)(struct FFTContext *s, float *output, const float *input);
- void (*imdctHalf)(struct FFTContext *s, float *output, const float *input);
- void (*mdctCalc)(struct FFTContext *s, float *output, const float *input);
- int splitRadix;
- int permutation;
-};
-
-enum {
- FF_MDCT_PERM_NONE = 0,
- 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);
@@ -196,7 +144,7 @@ private:
int _fftCoefsMinIndex[5];
int _fftCoefsMaxIndex[5];
int _fftLevelExp[6];
- RDFTContext _rdftCtx;
+ Common::RDFT *_rdft;
QDM2FFT _fft;
// I/O data
@@ -265,9 +213,9 @@ private:
void fill_coding_method_array(sb_int8_array tone_level_idx, sb_int8_array tone_level_idx_temp,
sb_int8_array coding_method, int nb_channels,
int c, int superblocktype_2_3, int cm_table_select);
- void synthfilt_build_sb_samples(GetBitContext *gb, int length, int sb_min, int sb_max);
- void init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitContext *gb, int length);
- void init_tone_level_dequantization(GetBitContext *gb, int length);
+ void synthfilt_build_sb_samples(Common::BitStream *gb, int length, int sb_min, int sb_max);
+ void init_quantized_coeffs_elem0(int8 *quantized_coeffs, Common::BitStream *gb, int length);
+ void init_tone_level_dequantization(Common::BitStream *gb, int length);
void process_subpacket_9(QDM2SubPNode *node);
void process_subpacket_10(QDM2SubPNode *node, int length);
void process_subpacket_11(QDM2SubPNode *node, int length);
@@ -276,7 +224,7 @@ private:
void qdm2_decode_super_block(void);
void qdm2_fft_init_coefficient(int sub_packet, int offset, int duration,
int channel, int exp, int phase);
- void qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b);
+ void qdm2_fft_decode_tones(int duration, Common::BitStream *gb, int b);
void qdm2_decode_fft_packets(void);
void qdm2_fft_generate_tone(FFTTone *tone);
void qdm2_fft_tone_synthesizer(uint8 sub_packet);
@@ -308,560 +256,6 @@ typedef signed long long int int64_t;
#define SB_DITHERING_NOISE(sb, noiseIdx) (_noiseTable[(noiseIdx)++] * sb_noise_attenuation[(sb)])
-static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize) {
- int bufferSize = (bitSize + 7) >> 3;
-
- if (bufferSize < 0 || bitSize < 0) {
- bufferSize = bitSize = 0;
- buffer = NULL;
- }
-
- s->buffer = buffer;
- s->sizeInBits = bitSize;
- s->bufferEnd = buffer + bufferSize;
- s->index = 0;
-}
-
-static inline int getBitsCount(GetBitContext *s) {
- return s->index;
-}
-
-static inline unsigned int getBits1(GetBitContext *s) {
- int index;
- uint8 result;
-
- index = s->index;
- result = s->buffer[index >> 3];
-
- result >>= (index & 0x07);
- result &= 1;
- index++;
- s->index = index;
-
- return result;
-}
-
-static inline unsigned int getBits(GetBitContext *s, int n) {
- int tmp, reCache, reIndex;
-
- reIndex = s->index;
-
- reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
-
- tmp = (reCache) & ((uint32)0xffffffff >> (32 - n));
-
- s->index = reIndex + n;
-
- return tmp;
-}
-
-static inline void skipBits(GetBitContext *s, int n) {
- s->index += n;
-}
-
-#define BITS_LEFT(length, gb) ((length) - getBitsCount((gb)))
-
-static int splitRadixPermutation(int i, int n, int inverse) {
- if (n <= 2)
- return i & 1;
-
- int m = n >> 1;
-
- if(!(i & m))
- return splitRadixPermutation(i, m, inverse) * 2;
-
- m >>= 1;
-
- if (inverse == !(i & m))
- return splitRadixPermutation(i, m, inverse) * 4 + 1;
-
- return splitRadixPermutation(i, m, inverse) * 4 - 1;
-}
-
-// sin(2*pi*x/n) for 0<=x<n/4, followed by n/2<=x<3n/4
-float ff_sin_16[8];
-float ff_sin_32[16];
-float ff_sin_64[32];
-float ff_sin_128[64];
-float ff_sin_256[128];
-float ff_sin_512[256];
-float ff_sin_1024[512];
-float ff_sin_2048[1024];
-float ff_sin_4096[2048];
-float ff_sin_8192[4096];
-float ff_sin_16384[8192];
-float ff_sin_32768[16384];
-float ff_sin_65536[32768];
-
-float *ff_sin_tabs[] = {
- NULL, NULL, NULL, NULL,
- ff_sin_16, ff_sin_32, ff_sin_64, ff_sin_128, ff_sin_256, ff_sin_512, ff_sin_1024,
- ff_sin_2048, ff_sin_4096, ff_sin_8192, ff_sin_16384, ff_sin_32768, ff_sin_65536,
-};
-
-// cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse
-float ff_cos_16[8];
-float ff_cos_32[16];
-float ff_cos_64[32];
-float ff_cos_128[64];
-float ff_cos_256[128];
-float ff_cos_512[256];
-float ff_cos_1024[512];
-float ff_cos_2048[1024];
-float ff_cos_4096[2048];
-float ff_cos_8192[4096];
-float ff_cos_16384[8192];
-float ff_cos_32768[16384];
-float ff_cos_65536[32768];
-
-float *ff_cos_tabs[] = {
- NULL, NULL, NULL, NULL,
- ff_cos_16, ff_cos_32, ff_cos_64, ff_cos_128, ff_cos_256, ff_cos_512, ff_cos_1024,
- ff_cos_2048, ff_cos_4096, ff_cos_8192, ff_cos_16384, ff_cos_32768, ff_cos_65536,
-};
-
-void initCosineTables(int index) {
- int m = 1 << index;
- double freq = 2 * M_PI / m;
- float *tab = ff_cos_tabs[index];
-
- for (int i = 0; i <= m / 4; i++)
- tab[i] = cos(i * freq);
-
- for (int i = 1; i < m / 4; i++)
- tab[m / 2 - i] = tab[i];
-}
-
-void fftPermute(FFTContext *s, FFTComplex *z) {
- const uint16 *revtab = s->revtab;
- int np = 1 << s->nbits;
-
- if (s->tmpBuf) {
- // TODO: handle split-radix permute in a more optimal way, probably in-place
- for (int j = 0; j < np; j++)
- s->tmpBuf[revtab[j]] = z[j];
- memcpy(z, s->tmpBuf, np * sizeof(FFTComplex));
- return;
- }
-
- // reverse
- for (int j = 0; j < np; j++) {
- int k = revtab[j];
- if (k < j) {
- FFTComplex tmp = z[k];
- z[k] = z[j];
- z[j] = tmp;
- }
- }
-}
-
-#define DECL_FFT(n,n2,n4) \
-static void fft##n(FFTComplex *z) { \
- fft##n2(z); \
- fft##n4(z + n4 * 2); \
- fft##n4(z + n4 * 3); \
- pass(z, ff_cos_##n, n4 / 2); \
-}
-
-#ifndef M_SQRT1_2
-#define M_SQRT1_2 7.0710678118654752440E-1
-#endif
-
-#define sqrthalf (float)M_SQRT1_2
-
-#define BF(x,y,a,b) { \
- x = a - b; \
- y = a + b; \
-}
-
-#define BUTTERFLIES(a0, a1, a2, a3) { \
- BF(t3, t5, t5, t1); \
- BF(a2.re, a0.re, a0.re, t5); \
- BF(a3.im, a1.im, a1.im, t3); \
- BF(t4, t6, t2, t6); \
- BF(a3.re, a1.re, a1.re, t4); \
- BF(a2.im, a0.im, a0.im, t6); \
-}
-
-// force loading all the inputs before storing any.
-// this is slightly slower for small data, but avoids store->load aliasing
-// for addresses separated by large powers of 2.
-#define BUTTERFLIES_BIG(a0, a1, a2, a3) { \
- float r0 = a0.re, i0 = a0.im, r1 = a1.re, i1 = a1.im; \
- BF(t3, t5, t5, t1); \
- BF(a2.re, a0.re, r0, t5); \
- BF(a3.im, a1.im, i1, t3); \
- BF(t4, t6, t2, t6); \
- BF(a3.re, a1.re, r1, t4); \
- BF(a2.im, a0.im, i0, t6); \
-}
-
-#define TRANSFORM(a0, a1, a2, a3, wre, wim) { \
- t1 = a2.re * wre + a2.im * wim; \
- t2 = a2.im * wre - a2.re * wim; \
- t5 = a3.re * wre - a3.im * wim; \
- t6 = a3.im * wre + a3.re * wim; \
- BUTTERFLIES(a0, a1, a2, a3) \
-}
-
-#define TRANSFORM_ZERO(a0, a1, a2, a3) { \
- t1 = a2.re; \
- t2 = a2.im; \
- t5 = a3.re; \
- t6 = a3.im; \
- BUTTERFLIES(a0, a1, a2, a3) \
-}
-
-// z[0...8n-1], w[1...2n-1]
-#define PASS(name) \
-static void name(FFTComplex *z, const float *wre, unsigned int n) { \
- float t1, t2, t3, t4, t5, t6; \
- int o1 = 2 * n; \
- int o2 = 4 * n; \
- int o3 = 6 * n; \
- const float *wim = wre + o1; \
- n--; \
- \
- TRANSFORM_ZERO(z[0], z[o1], z[o2], z[o3]); \
- TRANSFORM(z[1], z[o1 + 1], z[o2 + 1], z[o3 + 1], wre[1], wim[-1]); \
- \
- do { \
- z += 2; \
- wre += 2; \
- wim -= 2; \
- TRANSFORM(z[0], z[o1], z[o2], z[o3], wre[0], wim[0]); \
- TRANSFORM(z[1], z[o1 + 1],z[o2 + 1], z[o3 + 1], wre[1], wim[-1]); \
- } while(--n); \
-}
-
-PASS(pass)
-#undef BUTTERFLIES
-#define BUTTERFLIES BUTTERFLIES_BIG
-PASS(pass_big)
-
-static void fft4(FFTComplex *z) {
- float t1, t2, t3, t4, t5, t6, t7, t8;
-
- BF(t3, t1, z[0].re, z[1].re);
- BF(t8, t6, z[3].re, z[2].re);
- BF(z[2].re, z[0].re, t1, t6);
- BF(t4, t2, z[0].im, z[1].im);
- BF(t7, t5, z[2].im, z[3].im);
- BF(z[3].im, z[1].im, t4, t8);
- BF(z[3].re, z[1].re, t3, t7);
- BF(z[2].im, z[0].im, t2, t5);
-}
-
-static void fft8(FFTComplex *z) {
- float t1, t2, t3, t4, t5, t6, t7, t8;
-
- fft4(z);
-
- BF(t1, z[5].re, z[4].re, -z[5].re);
- BF(t2, z[5].im, z[4].im, -z[5].im);
- BF(t3, z[7].re, z[6].re, -z[7].re);
- BF(t4, z[7].im, z[6].im, -z[7].im);
- BF(t8, t1, t3, t1);
- BF(t7, t2, t2, t4);
- BF(z[4].re, z[0].re, z[0].re, t1);
- BF(z[4].im, z[0].im, z[0].im, t2);
- BF(z[6].re, z[2].re, z[2].re, t7);
- BF(z[6].im, z[2].im, z[2].im, t8);
-
- TRANSFORM(z[1], z[3], z[5], z[7], sqrthalf, sqrthalf);
-}
-
-#undef BF
-
-DECL_FFT(16,8,4)
-DECL_FFT(32,16,8)
-DECL_FFT(64,32,16)
-DECL_FFT(128,64,32)
-DECL_FFT(256,128,64)
-DECL_FFT(512,256,128)
-#define pass pass_big
-DECL_FFT(1024,512,256)
-DECL_FFT(2048,1024,512)
-DECL_FFT(4096,2048,1024)
-DECL_FFT(8192,4096,2048)
-DECL_FFT(16384,8192,4096)
-DECL_FFT(32768,16384,8192)
-DECL_FFT(65536,32768,16384)
-
-void fftCalc(FFTContext *s, FFTComplex *z) {
- static void (* const fftDispatch[])(FFTComplex *) = {
- fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
- fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
- };
-
- fftDispatch[s->nbits - 2](z);
-}
-
-// complex multiplication: p = a * b
-#define CMUL(pre, pim, are, aim, bre, bim) \
-{\
- float _are = (are); \
- float _aim = (aim); \
- float _bre = (bre); \
- float _bim = (bim); \
- (pre) = _are * _bre - _aim * _bim; \
- (pim) = _are * _bim + _aim * _bre; \
-}
-
-/**
- * Compute the middle half of the inverse MDCT of size N = 2^nbits,
- * thus excluding the parts that can be derived by symmetry
- * @param output N/2 samples
- * @param input N/2 samples
- */
-void imdctHalfC(FFTContext *s, float *output, const float *input) {
- const uint16 *revtab = s->revtab;
- const float *tcos = s->tcos;
- const float *tsin = s->tsin;
- FFTComplex *z = (FFTComplex *)output;
-
- int n = 1 << s->mdctBits;
- int n2 = n >> 1;
- int n4 = n >> 2;
- int n8 = n >> 3;
-
- // pre rotation
- const float *in1 = input;
- const float *in2 = input + n2 - 1;
- for (int k = 0; k < n4; k++) {
- int j = revtab[k];
- CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
- in1 += 2;
- in2 -= 2;
- }
-
- fftCalc(s, z);
-
- // post rotation + reordering
- for (int k = 0; k < n8; k++) {
- float r0, i0, r1, i1;
- CMUL(r0, i1, z[n8 - k - 1].im, z[n8 - k - 1].re, tsin[n8 - k - 1], tcos[n8 - k - 1]);
- CMUL(r1, i0, z[n8 + k].im, z[n8 + k].re, tsin[n8 + k], tcos[n8 + k]);
- z[n8 - k - 1].re = r0;
- z[n8 - k - 1].im = i0;
- z[n8 + k].re = r1;
- z[n8 + k].im = i1;
- }
-}
-
-/**
- * Compute inverse MDCT of size N = 2^nbits
- * @param output N samples
- * @param input N/2 samples
- */
-void imdctCalcC(FFTContext *s, float *output, const float *input) {
- int n = 1 << s->mdctBits;
- int n2 = n >> 1;
- int n4 = n >> 2;
-
- imdctHalfC(s, output + n4, input);
-
- for (int k = 0; k < n4; k++) {
- output[k] = -output[n2 - k - 1];
- output[n - k - 1] = output[n2 + k];
- }
-}
-
-/**
- * Compute MDCT of size N = 2^nbits
- * @param input N samples
- * @param out N/2 samples
- */
-void mdctCalcC(FFTContext *s, float *out, const float *input) {
- const uint16 *revtab = s->revtab;
- const float *tcos = s->tcos;
- const float *tsin = s->tsin;
- FFTComplex *x = (FFTComplex *)out;
-
- int n = 1 << s->mdctBits;
- int n2 = n >> 1;
- int n4 = n >> 2;
- int n8 = n >> 3;
- int n3 = 3 * n4;
-
- // pre rotation
- for (int i = 0; i < n8; i++) {
- float re = -input[2 * i + 3 * n4] - input[n3 - 1 - 2 * i];
- float im = -input[n4 + 2 * i] + input[n4 - 1 - 2 * i];
- int j = revtab[i];
- CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);
-
- re = input[2 * i] - input[n2 - 1 - 2 * i];
- im = -(input[n2 + 2 * i] + input[n - 1 - 2 * i]);
- j = revtab[n8 + i];
- CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
- }
-
- fftCalc(s, x);
-
- // post rotation
- for (int i = 0; i < n8; i++) {
- float r0, i0, r1, i1;
- CMUL(i1, r0, x[n8 - i - 1].re, x[n8 - i - 1].im, -tsin[n8 - i - 1], -tcos[n8 - i - 1]);
- CMUL(i0, r1, x[n8 + i].re, x[n8 + i].im, -tsin[n8 + i], -tcos[n8 + i]);
- x[n8 - i - 1].re = r0;
- x[n8 - i - 1].im = i0;
- x[n8 + i].re = r1;
- x[n8 + i].im = i1;
- }
-}
-
-int fftInit(FFTContext *s, int nbits, int inverse) {
- int i, j, m, n;
- float alpha, c1, s1, s2;
-
- if (nbits < 2 || nbits > 16)
- goto fail;
-
- s->nbits = nbits;
- n = 1 << nbits;
- s->tmpBuf = NULL;
-
- s->exptab = (FFTComplex *)malloc((n / 2) * sizeof(FFTComplex));
- if (!s->exptab)
- goto fail;
-
- s->revtab = (uint16 *)malloc(n * sizeof(uint16));
- if (!s->revtab)
- goto fail;
- s->inverse = inverse;
-
- s2 = inverse ? 1.0 : -1.0;
-
- s->fftPermute = fftPermute;
- s->fftCalc = fftCalc;
- s->imdctCalc = imdctCalcC;
- s->imdctHalf = imdctHalfC;
- s->mdctCalc = mdctCalcC;
- s->splitRadix = 1;
-
- if (s->splitRadix) {
- for (j = 4; j <= nbits; j++)
- initCosineTables(j);
-
- for (i = 0; i < n; i++)
- s->revtab[-splitRadixPermutation(i, n, s->inverse) & (n - 1)] = i;
-
- s->tmpBuf = (FFTComplex *)malloc(n * sizeof(FFTComplex));
- } else {
- for (i = 0; i < n / 2; i++) {
- alpha = 2 * M_PI * (float)i / (float)n;
- c1 = cos(alpha);
- s1 = sin(alpha) * s2;
- s->exptab[i].re = c1;
- s->exptab[i].im = s1;
- }
-
- //int np = 1 << nbits;
- //int nblocks = np >> 3;
- //int np2 = np >> 1;
-
- // compute bit reverse table
- for (i = 0; i < n; i++) {
- m = 0;
-
- for (j = 0; j < nbits; j++)
- m |= ((i >> j) & 1) << (nbits - j - 1);
-
- s->revtab[i] = m;
- }
- }
-
- return 0;
-
- fail:
- free(&s->revtab);
- free(&s->exptab);
- free(&s->tmpBuf);
- 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,
@@ -1283,43 +677,27 @@ void ff_mpa_synth_filter(int16 *synth_buf_ptr, int *synth_buf_offset,
* read the longest vlc code
* = (max_vlc_length + bits - 1) / bits
*/
-static int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth) {
- int reIndex;
- int reCache;
- int index;
- int code;
- int n;
-
- reIndex = s->index;
- reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
- index = reCache & (0xffffffff >> (32 - bits));
- code = table[index][0];
- n = table[index][1];
-
- if (maxDepth > 1 && n < 0){
- reIndex += bits;
- reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
+static int getVlc2(Common::BitStream *s, int16 (*table)[2], int bits, int maxDepth) {
+ int index = s->peekBits(bits);
+ int code = table[index][0];
+ int n = table[index][1];
+ if (maxDepth > 1 && n < 0) {
+ s->skip(bits);
int nbBits = -n;
-
- index = (reCache & (0xffffffff >> (32 - nbBits))) + code;
+ index = s->peekBits(-n) + code;
code = table[index][0];
n = table[index][1];
- if(maxDepth > 2 && n < 0) {
- reIndex += nbBits;
- reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
-
- nbBits = -n;
-
- index = (reCache & (0xffffffff >> (32 - nbBits))) + code;
+ if (maxDepth > 2 && n < 0) {
+ s->skip(nbBits);
+ index = s->getBits(-n) + code;
code = table[index][0];
n = table[index][1];
}
}
- reCache >>= n;
- s->index = reIndex + n;
+ s->skip(n);
return code;
}
@@ -1483,9 +861,9 @@ void initVlcSparse(VLC *vlc, int nb_bits, int nb_codes,
const void *symbols, int symbols_wrap, int symbols_size) {
vlc->bits = nb_bits;
- if(vlc->table_size && vlc->table_size == vlc->table_allocated) {
+ if (vlc->table_size && vlc->table_size == vlc->table_allocated) {
return;
- } else if(vlc->table_size) {
+ } else if (vlc->table_size) {
error("called on a partially initialized table");
}
@@ -1830,7 +1208,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);
@@ -1845,29 +1223,30 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::F
}
QDM2Stream::~QDM2Stream() {
+ delete _rdft;
delete[] _compressedData;
}
-static int qdm2_get_vlc(GetBitContext *gb, VLC *vlc, int flag, int depth) {
+static int qdm2_get_vlc(Common::BitStream *gb, VLC *vlc, int flag, int depth) {
int value = getVlc2(gb, vlc->table, vlc->bits, depth);
// stage-2, 3 bits exponent escape sequence
if (value-- == 0)
- value = getBits(gb, getBits (gb, 3) + 1);
+ value = gb->getBits(gb->getBits(3) + 1);
// stage-3, optional
if (flag) {
int tmp = vlc_stage3_values[value];
if ((value & ~3) > 0)
- tmp += getBits(gb, (value >> 2));
+ tmp += gb->getBits(value >> 2);
value = tmp;
}
return value;
}
-static int qdm2_get_se_vlc(VLC *vlc, GetBitContext *gb, int depth)
+static int qdm2_get_se_vlc(VLC *vlc, Common::BitStream *gb, int depth)
{
int value = qdm2_get_vlc(gb, vlc, 0, depth);
@@ -1893,35 +1272,6 @@ static uint16 qdm2_packet_checksum(const uint8 *data, int length, int value) {
}
/**
- * Fills a QDM2SubPacket structure with packet type, size, and data pointer.
- *
- * @param gb bitreader context
- * @param sub_packet packet under analysis
- */
-static void qdm2_decode_sub_packet_header(GetBitContext *gb, QDM2SubPacket *sub_packet)
-{
- sub_packet->type = getBits (gb, 8);
-
- if (sub_packet->type == 0) {
- sub_packet->size = 0;
- sub_packet->data = NULL;
- } else {
- sub_packet->size = getBits (gb, 8);
-
- if (sub_packet->type & 0x80) {
- sub_packet->size <<= 8;
- sub_packet->size |= getBits (gb, 8);
- sub_packet->type &= 0x7f;
- }
-
- if (sub_packet->type == 0x7f)
- sub_packet->type |= (getBits (gb, 8) << 8);
-
- sub_packet->data = &gb->buffer[getBitsCount(gb) / 8]; // FIXME: this depends on bitreader internal data
- }
-}
-
-/**
* Return node pointer to first packet of requested type in list.
*
* @param list list of subpackets to be scanned
@@ -2003,7 +1353,7 @@ void QDM2Stream::fix_coding_method_array(int sb, int channels, sb_int8_array cod
for (ch = 0; ch < channels; ch++) {
for (j = 0; j < 64; ) {
- if((coding_method[ch][sb][j] - 8) > 22) {
+ if ((coding_method[ch][sb][j] - 8) > 22) {
run = 1;
case_val = 8;
} else {
@@ -2256,7 +1606,7 @@ void QDM2Stream::fill_coding_method_array(sb_int8_array tone_level_idx, sb_int8_
* @param sb_min lower subband processed (sb_min included)
* @param sb_max higher subband processed (sb_max excluded)
*/
-void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int sb_min, int sb_max) {
+void QDM2Stream::synthfilt_build_sb_samples(Common::BitStream *gb, int length, int sb_min, int sb_max) {
int sb, j, k, n, ch, run, channels;
int joined_stereo, zero_encoding, chs;
int type34_first;
@@ -2282,12 +1632,12 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
else if (sb >= 24)
joined_stereo = 1;
else
- joined_stereo = (BITS_LEFT(length,gb) >= 1) ? getBits1 (gb) : 0;
+ joined_stereo = ((length - gb->pos()) >= 1) ? gb->getBit() : 0;
if (joined_stereo) {
- if (BITS_LEFT(length,gb) >= 16)
+ if ((length - gb->pos()) >= 16)
for (j = 0; j < 16; j++)
- sign_bits[j] = getBits1(gb);
+ sign_bits[j] = gb->getBit();
for (j = 0; j < 64; j++)
if (_codingMethod[1][sb][j] > _codingMethod[0][sb][j])
@@ -2298,22 +1648,22 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
}
for (ch = 0; ch < channels; ch++) {
- zero_encoding = (BITS_LEFT(length,gb) >= 1) ? getBits1(gb) : 0;
+ zero_encoding = ((length - gb->pos()) >= 1) ? gb->getBit() : 0;
type34_predictor = 0.0;
type34_first = 1;
for (j = 0; j < 128; ) {
switch (_codingMethod[ch][sb][j / 2]) {
case 8:
- if (BITS_LEFT(length,gb) >= 10) {
+ if ((length - gb->pos()) >= 10) {
if (zero_encoding) {
for (k = 0; k < 5; k++) {
if ((j + 2 * k) >= 128)
break;
- samples[2 * k] = getBits1(gb) ? dequant_1bit[joined_stereo][2 * getBits1(gb)] : 0;
+ samples[2 * k] = gb->getBit() ? dequant_1bit[joined_stereo][2 * gb->getBit()] : 0;
}
} else {
- n = getBits(gb, 8);
+ n = gb->getBits(8);
for (k = 0; k < 5; k++)
samples[2 * k] = dequant_1bit[joined_stereo][_randomDequantIndex[n][k]];
}
@@ -2327,10 +1677,10 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
break;
case 10:
- if (BITS_LEFT(length,gb) >= 1) {
+ if ((length - gb->pos()) >= 1) {
double f = 0.81;
- if (getBits1(gb))
+ if (gb->getBit())
f = -f;
f -= _noiseSamples[((sb + 1) * (j +5 * ch + 1)) & 127] * 9.0 / 40.0;
samples[0] = f;
@@ -2341,15 +1691,15 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
break;
case 16:
- if (BITS_LEFT(length,gb) >= 10) {
+ if ((length - gb->pos()) >= 10) {
if (zero_encoding) {
for (k = 0; k < 5; k++) {
if ((j + k) >= 128)
break;
- samples[k] = (getBits1(gb) == 0) ? 0 : dequant_1bit[joined_stereo][2 * getBits1(gb)];
+ samples[k] = (gb->getBit() == 0) ? 0 : dequant_1bit[joined_stereo][2 * gb->getBit()];
}
} else {
- n = getBits (gb, 8);
+ n = gb->getBits(8);
for (k = 0; k < 5; k++)
samples[k] = dequant_1bit[joined_stereo][_randomDequantIndex[n][k]];
}
@@ -2361,8 +1711,8 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
break;
case 24:
- if (BITS_LEFT(length,gb) >= 7) {
- n = getBits(gb, 7);
+ if ((length - gb->pos()) >= 7) {
+ n = gb->getBits(7);
for (k = 0; k < 3; k++)
samples[k] = (_randomDequantType24[n][k] - 2.0) * 0.5;
} else {
@@ -2373,7 +1723,7 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
break;
case 30:
- if (BITS_LEFT(length,gb) >= 4)
+ if ((length - gb->pos()) >= 4)
samples[0] = type30_dequant[qdm2_get_vlc(gb, &_vlcTabType30, 0, 1)];
else
samples[0] = SB_DITHERING_NOISE(sb, _noiseIdx);
@@ -2382,10 +1732,10 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
break;
case 34:
- if (BITS_LEFT(length,gb) >= 7) {
+ if ((length - gb->pos()) >= 7) {
if (type34_first) {
- type34_div = (float)(1 << getBits(gb, 2));
- samples[0] = ((float)getBits(gb, 5) - 16.0) / 15.0;
+ type34_div = (float)(1 << gb->getBits(2));
+ samples[0] = ((float)gb->getBits(5) - 16.0) / 15.0;
type34_predictor = samples[0];
type34_first = 0;
} else {
@@ -2436,21 +1786,21 @@ void QDM2Stream::synthfilt_build_sb_samples(GetBitContext *gb, int length, int s
* @param gb bitreader context
* @param length packet length in bits
*/
-void QDM2Stream::init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitContext *gb, int length) {
+void QDM2Stream::init_quantized_coeffs_elem0(int8 *quantized_coeffs, Common::BitStream *gb, int length) {
int i, k, run, level, diff;
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
return;
level = qdm2_get_vlc(gb, &_vlcTabLevel, 0, 2);
quantized_coeffs[0] = level;
for (i = 0; i < 7; ) {
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
break;
run = qdm2_get_vlc(gb, &_vlcTabRun, 0, 1) + 1;
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
break;
diff = qdm2_get_se_vlc(&_vlcTabDiff, gb, 2);
@@ -2470,13 +1820,13 @@ void QDM2Stream::init_quantized_coeffs_elem0(int8 *quantized_coeffs, GetBitConte
* @param gb bitreader context
* @param length packet length in bits
*/
-void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
+void QDM2Stream::init_tone_level_dequantization(Common::BitStream *gb, int length) {
int sb, j, k, n, ch;
for (ch = 0; ch < _channels; ch++) {
init_quantized_coeffs_elem0(_quantizedCoeffs[ch][0], gb, length);
- if (BITS_LEFT(length,gb) < 16) {
+ if ((length - gb->pos()) < 16) {
memset(_quantizedCoeffs[ch][0], 0, 8);
break;
}
@@ -2487,11 +1837,11 @@ void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
for (sb = 0; sb < n; sb++)
for (ch = 0; ch < _channels; ch++)
for (j = 0; j < 8; j++) {
- if (BITS_LEFT(length,gb) < 1)
+ if ((length - gb->pos()) < 1)
break;
- if (getBits1(gb)) {
+ if (gb->getBit()) {
for (k=0; k < 8; k++) {
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
break;
_toneLevelIdxHi1[ch][sb][j][k] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxHi1, 0, 2);
}
@@ -2505,7 +1855,7 @@ void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
for (sb = 0; sb < n; sb++)
for (ch = 0; ch < _channels; ch++) {
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
break;
_toneLevelIdxHi2[ch][sb] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxHi2, 0, 2);
if (sb > 19)
@@ -2520,7 +1870,7 @@ void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
for (sb = 0; sb < n; sb++) {
for (ch = 0; ch < _channels; ch++) {
for (j = 0; j < 8; j++) {
- if (BITS_LEFT(length,gb) < 16)
+ if ((length - gb->pos()) < 16)
break;
_toneLevelIdxMid[ch][sb][j] = qdm2_get_vlc(gb, &_vlcTabToneLevelIdxMid, 0, 2) - 32;
}
@@ -2534,10 +1884,10 @@ void QDM2Stream::init_tone_level_dequantization(GetBitContext *gb, int length) {
* @param node pointer to node with packet
*/
void QDM2Stream::process_subpacket_9(QDM2SubPNode *node) {
- GetBitContext gb;
int i, j, k, n, ch, run, level, diff;
- initGetBits(&gb, node->packet->data, node->packet->size*8);
+ Common::MemoryReadStream d(node->packet->data, node->packet->size*8);
+ Common::BitStream32LELSB gb(&d);
n = coeff_per_sb_for_avg[_coeffPerSbSelect][QDM2_SB_USED(_subSampling) - 1] + 1; // same as averagesomething function
@@ -2570,9 +1920,8 @@ void QDM2Stream::process_subpacket_9(QDM2SubPNode *node) {
* @param length packet length in bits
*/
void QDM2Stream::process_subpacket_10(QDM2SubPNode *node, int length) {
- GetBitContext gb;
-
- initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ Common::MemoryReadStream d(((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ Common::BitStream32LELSB gb(&d);
if (length != 0) {
init_tone_level_dequantization(&gb, length);
@@ -2589,11 +1938,11 @@ void QDM2Stream::process_subpacket_10(QDM2SubPNode *node, int length) {
* @param length packet length in bit
*/
void QDM2Stream::process_subpacket_11(QDM2SubPNode *node, int length) {
- GetBitContext gb;
+ Common::MemoryReadStream d(((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ Common::BitStream32LELSB gb(&d);
- initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
if (length >= 32) {
- int c = getBits (&gb, 13);
+ int c = gb.getBits(13);
if (c > 3)
fill_coding_method_array(_toneLevelIdx, _toneLevelIdxTemp, _codingMethod,
@@ -2610,9 +1959,9 @@ void QDM2Stream::process_subpacket_11(QDM2SubPNode *node, int length) {
* @param length packet length in bits
*/
void QDM2Stream::process_subpacket_12(QDM2SubPNode *node, int length) {
- GetBitContext gb;
+ Common::MemoryReadStream d(((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
+ Common::BitStream32LELSB gb(&d);
- initGetBits(&gb, ((node == NULL) ? _emptyBuffer : node->packet->data), ((node == NULL) ? 0 : node->packet->size*8));
synthfilt_build_sb_samples(&gb, length, 8, QDM2_SB_USED(_subSampling));
}
@@ -2652,7 +2001,6 @@ void QDM2Stream::process_synthesis_subpackets(QDM2SubPNode *list) {
*
*/
void QDM2Stream::qdm2_decode_super_block(void) {
- GetBitContext gb;
struct QDM2SubPacket header, *packet;
int i, packet_bytes, sub_packet_size, subPacketsD;
unsigned int next_index = 0;
@@ -2666,8 +2014,28 @@ void QDM2Stream::qdm2_decode_super_block(void) {
average_quantized_coeffs(); // average elements in quantized_coeffs[max_ch][10][8]
- initGetBits(&gb, _compressedData, _packetSize*8);
- qdm2_decode_sub_packet_header(&gb, &header);
+ Common::MemoryReadStream *d = new Common::MemoryReadStream(_compressedData, _packetSize*8);
+ Common::BitStream *gb = new Common::BitStream32LELSB(d);
+ //qdm2_decode_sub_packet_header
+ header.type = gb->getBits(8);
+
+ if (header.type == 0) {
+ header.size = 0;
+ header.data = NULL;
+ } else {
+ header.size = gb->getBits(8);
+
+ if (header.type & 0x80) {
+ header.size <<= 8;
+ header.size |= gb->getBits(8);
+ header.type &= 0x7f;
+ }
+
+ if (header.type == 0x7f)
+ header.type |= (gb->getBits(8) << 8);
+
+ header.data = &_compressedData[gb->pos() / 8];
+ }
if (header.type < 2 || header.type >= 8) {
_hasErrors = true;
@@ -2676,12 +2044,15 @@ void QDM2Stream::qdm2_decode_super_block(void) {
}
_superblocktype_2_3 = (header.type == 2 || header.type == 3);
- packet_bytes = (_packetSize - getBitsCount(&gb) / 8);
+ packet_bytes = (_packetSize - gb->pos() / 8);
- initGetBits(&gb, header.data, header.size*8);
+ delete gb;
+ delete d;
+ d = new Common::MemoryReadStream(header.data, header.size*8);
+ gb = new Common::BitStream32LELSB(d);
if (header.type == 2 || header.type == 4 || header.type == 5) {
- int csum = 257 * getBits(&gb, 8) + 2 * getBits(&gb, 8);
+ int csum = 257 * gb->getBits(8) + 2 * gb->getBits(8);
csum = qdm2_packet_checksum(_compressedData, _packetSize, csum);
@@ -2708,8 +2079,11 @@ void QDM2Stream::qdm2_decode_super_block(void) {
_subPacketListA[i - 1].next = &_subPacketListA[i];
// seek to next block
- initGetBits(&gb, header.data, header.size*8);
- skipBits(&gb, next_index*8);
+ delete gb;
+ delete d;
+ d = new Common::MemoryReadStream(header.data, header.size*8);
+ gb = new Common::BitStream32LELSB(d);
+ gb->skip(next_index*8);
if (next_index >= header.size)
break;
@@ -2717,8 +2091,28 @@ void QDM2Stream::qdm2_decode_super_block(void) {
// decode subpacket
packet = &_subPackets[i];
- qdm2_decode_sub_packet_header(&gb, packet);
- next_index = packet->size + getBitsCount(&gb) / 8;
+ //qdm2_decode_sub_packet_header
+ packet->type = gb->getBits(8);
+
+ if (packet->type == 0) {
+ packet->size = 0;
+ packet->data = NULL;
+ } else {
+ packet->size = gb->getBits(8);
+
+ if (packet->type & 0x80) {
+ packet->size <<= 8;
+ packet->size |= gb->getBits(8);
+ packet->type &= 0x7f;
+ }
+
+ if (packet->type == 0x7f)
+ packet->type |= (gb->getBits(8) << 8);
+
+ packet->data = &header.data[gb->pos() / 8];
+ }
+
+ next_index = packet->size + gb->pos() / 8;
sub_packet_size = ((packet->size > 0xff) ? 1 : 0) + packet->size + 2;
if (packet->type == 0)
@@ -2738,18 +2132,22 @@ void QDM2Stream::qdm2_decode_super_block(void) {
// add subpacket to related list
if (packet->type == 8) {
error("Unsupported packet type 8");
+ delete gb;
+ delete d;
return;
} else if (packet->type >= 9 && packet->type <= 12) {
// packets for MPEG Audio like Synthesis Filter
QDM2_LIST_ADD(_subPacketListD, subPacketsD, packet);
} else if (packet->type == 13) {
for (j = 0; j < 6; j++)
- _fftLevelExp[j] = getBits(&gb, 6);
+ _fftLevelExp[j] = gb->getBits(6);
} else if (packet->type == 14) {
for (j = 0; j < 6; j++)
- _fftLevelExp[j] = qdm2_get_vlc(&gb, &_fftLevelExpVlc, 0, 2);
+ _fftLevelExp[j] = qdm2_get_vlc(gb, &_fftLevelExpVlc, 0, 2);
} else if (packet->type == 15) {
error("Unsupported packet type 15");
+ delete gb;
+ delete d;
return;
} else if (packet->type >= 16 && packet->type < 48 && !fft_subpackets[packet->type - 16]) {
// packets for FFT
@@ -2767,6 +2165,8 @@ void QDM2Stream::qdm2_decode_super_block(void) {
process_subpacket_12(NULL, 0);
}
// ****************************************************************
+ delete gb;
+ delete d;
}
void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int duration,
@@ -2782,7 +2182,7 @@ void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int durat
_fftCoefsIndex++;
}
-void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
+void QDM2Stream::qdm2_fft_decode_tones(int duration, Common::BitStream *gb, int b) {
int channel, stereo, phase, exp;
int local_int_4, local_int_8, stereo_phase, local_int_10;
int local_int_14, stereo_exp, local_int_20, local_int_28;
@@ -2823,8 +2223,8 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
local_int_14 = (offset >> local_int_8);
if (_channels > 1) {
- channel = getBits1(gb);
- stereo = getBits1(gb);
+ channel = gb->getBit();
+ stereo = gb->getBit();
} else {
channel = 0;
stereo = 0;
@@ -2834,7 +2234,7 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
exp += _fftLevelExp[fft_level_index_table[local_int_14]];
exp = (exp < 0) ? 0 : exp;
- phase = getBits(gb, 3);
+ phase = gb->getBits(3);
stereo_exp = 0;
stereo_phase = 0;
@@ -2859,7 +2259,6 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
void QDM2Stream::qdm2_decode_fft_packets(void) {
int i, j, min, max, value, type, unknown_flag;
- GetBitContext gb;
if (_subPacketListB[0].packet == NULL)
return;
@@ -2892,7 +2291,8 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
return;
// decode FFT tones
- initGetBits(&gb, packet->data, packet->size*8);
+ Common::MemoryReadStream d(packet->data, packet->size*8);
+ Common::BitStream32LELSB gb(&d);
if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16])
unknown_flag = 1;
@@ -2913,7 +2313,7 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
}
} else if (type == 46) {
for (j=0; j < 6; j++)
- _fftLevelExp[j] = getBits(&gb, 6);
+ _fftLevelExp[j] = gb.getBits(6);
for (j=0; j < 4; j++) {
qdm2_fft_decode_tones(j, &gb, unknown_flag);
}
@@ -3045,15 +2445,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];
}
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 762e86959d..0588650ec6 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -62,38 +62,42 @@ private:
};
/**
- * An AudioStream wrapper that cuts off the amount of samples read after a
- * given time length is reached.
+ * An AudioStream wrapper that forces audio to be played in mono.
+ * It currently just ignores the right channel if stereo.
*/
-class LimitingAudioStream : public AudioStream {
+class ForcedMonoAudioStream : public AudioStream {
public:
- LimitingAudioStream(AudioStream *parentStream, const Audio::Timestamp &length,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) :
- _parentStream(parentStream), _samplesRead(0), _disposeAfterUse(disposeAfterUse),
- _totalSamples(length.convertToFramerate(getRate()).totalNumberOfFrames() * getChannels()) {}
+ ForcedMonoAudioStream(AudioStream *parentStream, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) :
+ _parentStream(parentStream), _disposeAfterUse(disposeAfterUse) {}
- ~LimitingAudioStream() {
+ ~ForcedMonoAudioStream() {
if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _parentStream;
+ delete _parentStream;
}
int readBuffer(int16 *buffer, const int numSamples) {
- // Cap us off so we don't read past _totalSamples
- int samplesRead = _parentStream->readBuffer(buffer, MIN<int>(numSamples, _totalSamples - _samplesRead));
- _samplesRead += samplesRead;
- return samplesRead;
+ if (!_parentStream->isStereo())
+ return _parentStream->readBuffer(buffer, numSamples);
+
+ int16 temp[2];
+ int samples = 0;
+
+ while (samples < numSamples && !endOfData()) {
+ _parentStream->readBuffer(temp, 2);
+ *buffer++ = temp[0];
+ samples++;
+ }
+
+ return samples;
}
- bool endOfData() const { return _parentStream->endOfData() || _samplesRead >= _totalSamples; }
- bool isStereo() const { return _parentStream->isStereo(); }
+ bool endOfData() const { return _parentStream->endOfData(); }
+ bool isStereo() const { return false; }
int getRate() const { return _parentStream->getRate(); }
private:
- int getChannels() const { return isStereo() ? 2 : 1; }
-
AudioStream *_parentStream;
DisposeAfterUse::Flag _disposeAfterUse;
- uint32 _totalSamples, _samplesRead;
};
QuickTimeAudioDecoder::QuickTimeAudioDecoder() : Common::QuickTimeParser() {
@@ -191,7 +195,7 @@ QuickTimeAudioDecoder::QuickTimeAudioTrack::QuickTimeAudioTrack(QuickTimeAudioDe
if (entry->getCodecTag() == MKTAG('r', 'a', 'w', ' ') || entry->getCodecTag() == MKTAG('t', 'w', 'o', 's'))
_parentTrack->sampleSize = (entry->_bitsPerSample / 8) * entry->_channels;
-
+
// Initialize our edit parser too
_curEdit = 0;
enterNewEdit(Timestamp());
@@ -224,7 +228,7 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::queueAudio(const Timestamp &len
_skipSamples = Timestamp();
}
- queueStream(new LimitingAudioStream(new SilentAudioStream(getRate(), isStereo()), editLength), editLength);
+ queueStream(makeLimitingAudioStream(new SilentAudioStream(getRate(), isStereo()), editLength), editLength);
_curEdit++;
enterNewEdit(nextEditTime);
} else {
@@ -250,7 +254,7 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::queueAudio(const Timestamp &len
// we move on to the next edit
if (trackPosition >= nextEditTime || _curChunk >= _parentTrack->chunkCount) {
chunkLength = nextEditTime.convertToFramerate(getRate()) - getCurrentTrackTime();
- stream = new LimitingAudioStream(stream, chunkLength);
+ stream = makeLimitingAudioStream(stream, chunkLength);
_curEdit++;
enterNewEdit(nextEditTime);
@@ -299,7 +303,7 @@ bool QuickTimeAudioDecoder::QuickTimeAudioTrack::seek(const Timestamp &where) {
_queue = createStream();
_samplesQueued = 0;
- if (where > getLength()) {
+ if (where >= getLength()) {
// We're done
_curEdit = _parentTrack->editCount;
return true;
@@ -391,9 +395,9 @@ AudioStream *QuickTimeAudioDecoder::QuickTimeAudioTrack::readAudioChunk(uint chu
}
void QuickTimeAudioDecoder::QuickTimeAudioTrack::skipSamples(const Timestamp &length, AudioStream *stream) {
- uint32 sampleCount = length.convertToFramerate(getRate()).totalNumberOfFrames();
+ int32 sampleCount = length.convertToFramerate(getRate()).totalNumberOfFrames();
- if (sampleCount == 0)
+ if (sampleCount <= 0)
return;
if (isStereo())
@@ -410,7 +414,7 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::skipSamples(const Timestamp &le
}
void QuickTimeAudioDecoder::QuickTimeAudioTrack::findEdit(const Timestamp &position) {
- for (_curEdit = 0; _curEdit < _parentTrack->editCount && position < Timestamp(0, _parentTrack->editList[_curEdit].timeOffset, _decoder->_timeScale); _curEdit++)
+ for (_curEdit = 0; _curEdit < _parentTrack->editCount - 1 && position > Timestamp(0, _parentTrack->editList[_curEdit].timeOffset, _decoder->_timeScale); _curEdit++)
;
enterNewEdit(position);
@@ -422,7 +426,7 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::enterNewEdit(const Timestamp &p
// If we're at the end of the edit list, there's nothing else for us to do here
if (allDataRead())
return;
-
+
// For an empty edit, we may need to adjust the start time
if (_parentTrack->editList[_curEdit].mediaTime == -1) {
// Just invalidate the current media position (and make sure the scale
@@ -495,7 +499,13 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::enterNewEdit(const Timestamp &p
}
void QuickTimeAudioDecoder::QuickTimeAudioTrack::queueStream(AudioStream *stream, const Timestamp &length) {
- _queue->queueAudioStream(stream, DisposeAfterUse::YES);
+ // If the samples are stereo and the container is mono, force the samples
+ // to be mono.
+ if (stream->isStereo() && !isStereo())
+ _queue->queueAudioStream(new ForcedMonoAudioStream(stream, DisposeAfterUse::YES), DisposeAfterUse::YES);
+ else
+ _queue->queueAudioStream(stream, DisposeAfterUse::YES);
+
_samplesQueued += length.convertToFramerate(getRate()).totalNumberOfFrames();
}
diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h
index 4dd1a57710..4c0b93488e 100644
--- a/audio/decoders/quicktime.h
+++ b/audio/decoders/quicktime.h
@@ -25,6 +25,7 @@
* Sound decoder used in engines:
* - groovie
* - mohawk
+ * - pegasus
* - sci
*/
diff --git a/audio/decoders/quicktime_intern.h b/audio/decoders/quicktime_intern.h
index efc97cbd13..f1ab037d89 100644
--- a/audio/decoders/quicktime_intern.h
+++ b/audio/decoders/quicktime_intern.h
@@ -88,7 +88,7 @@ protected:
private:
QuickTimeAudioDecoder *_decoder;
- Track *_parentTrack;
+ Track *_parentTrack;
QueuingAudioStream *_queue;
uint _curChunk;
Timestamp _curMediaPos, _skipSamples;
@@ -115,7 +115,7 @@ protected:
~AudioSampleDesc();
bool isAudioCodecSupported() const;
-
+
AudioStream *createAudioStream(Common::SeekableReadStream *stream) const;
void initCodec();
diff --git a/audio/decoders/voc.cpp b/audio/decoders/voc.cpp
index f0b5b2777d..fa330c6f2c 100644
--- a/audio/decoders/voc.cpp
+++ b/audio/decoders/voc.cpp
@@ -321,9 +321,14 @@ void VocStream::preProcess() {
// In case we hit a "Terminator" block we also break here.
if (_stream->eos() || block.code == 0)
break;
- // We also allow 128 as terminator, since Simon 1 Amiga CD32 uses it.
- if (block.code == 128) {
- debug(3, "VocStream::preProcess: Caught 128 as terminator");
+ // We will allow invalid block numbers as terminators. This is needed,
+ // since some games ship broken VOC files. The following occasions are
+ // known:
+ // - 128 is used as terminator in Simon 1 Amiga CD32
+ // - Full Throttle contains a VOC file with an incorrect block length
+ // resulting in a sample (127) to be read as block code.
+ if (block.code > 9) {
+ warning("VocStream::preProcess: Caught %d as terminator", block.code);
break;
}
@@ -482,7 +487,8 @@ void VocStream::preProcess() {
default:
warning("Unhandled code %d in VOC file (len %d)", block.code, block.length);
- return;
+ // Skip the whole block and try to use the next one.
+ skip = block.length;
}
// Premature end of stream => error!