aboutsummaryrefslogtreecommitdiff
path: root/sound/decoders
diff options
context:
space:
mode:
authorMax Horn2011-02-09 01:09:01 +0000
committerMax Horn2011-02-09 01:09:01 +0000
commit42ab839dd6c8a1570b232101eb97f4e54de57935 (patch)
tree3b763d8913a87482b793e0348c88b9a5f40eecc9 /sound/decoders
parent386203a3d6ce1abf457c9110d695408ec5f01b85 (diff)
downloadscummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.tar.gz
scummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.tar.bz2
scummvm-rg350-42ab839dd6c8a1570b232101eb97f4e54de57935.zip
AUDIO: Rename sound/ dir to audio/
svn-id: r55850
Diffstat (limited to 'sound/decoders')
-rw-r--r--sound/decoders/adpcm.cpp851
-rw-r--r--sound/decoders/adpcm.h90
-rw-r--r--sound/decoders/aiff.cpp186
-rw-r--r--sound/decoders/aiff.h71
-rw-r--r--sound/decoders/flac.cpp745
-rw-r--r--sound/decoders/flac.h75
-rw-r--r--sound/decoders/iff_sound.cpp130
-rw-r--r--sound/decoders/iff_sound.h47
-rw-r--r--sound/decoders/mac_snd.cpp116
-rw-r--r--sound/decoders/mac_snd.h58
-rw-r--r--sound/decoders/mp3.cpp375
-rw-r--r--sound/decoders/mp3.h76
-rw-r--r--sound/decoders/raw.cpp356
-rw-r--r--sound/decoders/raw.h153
-rw-r--r--sound/decoders/vag.cpp150
-rw-r--r--sound/decoders/vag.h60
-rw-r--r--sound/decoders/voc.cpp403
-rw-r--r--sound/decoders/voc.h107
-rw-r--r--sound/decoders/vorbis.cpp262
-rw-r--r--sound/decoders/vorbis.h75
-rw-r--r--sound/decoders/wave.cpp194
-rw-r--r--sound/decoders/wave.h84
22 files changed, 0 insertions, 4664 deletions
diff --git a/sound/decoders/adpcm.cpp b/sound/decoders/adpcm.cpp
deleted file mode 100644
index 4b5e6a5b84..0000000000
--- a/sound/decoders/adpcm.cpp
+++ /dev/null
@@ -1,851 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/endian.h"
-
-#include "sound/decoders/adpcm.h"
-#include "sound/audiostream.h"
-
-
-namespace Audio {
-
-class ADPCMStream : public RewindableAudioStream {
-protected:
- Common::SeekableReadStream *_stream;
- const DisposeAfterUse::Flag _disposeAfterUse;
- const int32 _startpos;
- const int32 _endpos;
- const int _channels;
- const uint32 _blockAlign;
- uint32 _blockPos[2];
- const int _rate;
-
- struct {
- // OKI/IMA
- struct {
- int32 last;
- int32 stepIndex;
- } ima_ch[2];
- } _status;
-
- virtual void reset();
- int16 stepAdjust(byte);
-
-public:
- ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
- ~ADPCMStream();
-
- 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 rewind();
-};
-
-// Routines to convert 12 bit linear samples to the
-// Dialogic or Oki ADPCM coding format aka VOX.
-// See also <http://www.comptek.ru/telephony/tnotes/tt1-13.html>
-//
-// IMA ADPCM support is based on
-// <http://wiki.multimedia.cx/index.php?title=IMA_ADPCM>
-//
-// In addition, also MS IMA ADPCM is supported. See
-// <http://wiki.multimedia.cx/index.php?title=Microsoft_IMA_ADPCM>.
-
-ADPCMStream::ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : _stream(stream),
- _disposeAfterUse(disposeAfterUse),
- _startpos(stream->pos()),
- _endpos(_startpos + size),
- _channels(channels),
- _blockAlign(blockAlign),
- _rate(rate) {
-
- reset();
-}
-
-ADPCMStream::~ADPCMStream() {
- if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _stream;
-}
-
-void ADPCMStream::reset() {
- memset(&_status, 0, sizeof(_status));
- _blockPos[0] = _blockPos[1] = _blockAlign; // To make sure first header is read
-}
-
-bool ADPCMStream::rewind() {
- // TODO: Error checking.
- reset();
- _stream->seek(_startpos);
- return true;
-}
-
-
-#pragma mark -
-
-
-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) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-protected:
- int16 decodeOKI(byte);
-};
-
-int Oki_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- byte data;
-
- assert(numSamples % 2 == 0);
-
- 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);
- }
- return samples;
-}
-
-static const int16 okiStepSize[49] = {
- 16, 17, 19, 21, 23, 25, 28, 31,
- 34, 37, 41, 45, 50, 55, 60, 66,
- 73, 80, 88, 97, 107, 118, 130, 143,
- 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658,
- 724, 796, 876, 963, 1060, 1166, 1282, 1411,
- 1552
-};
-
-// Decode Linear to ADPCM
-int16 Oki_ADPCMStream::decodeOKI(byte code) {
- int16 diff, E, samp;
-
- E = (2 * (code & 0x7) + 1) * okiStepSize[_status.ima_ch[0].stepIndex] / 8;
- diff = (code & 0x08) ? -E : E;
- samp = _status.ima_ch[0].last + diff;
- // Clip the values to +/- 2^11 (supposed to be 12 bits)
- samp = CLIP<int16>(samp, -2048, 2047);
-
- _status.ima_ch[0].last = samp;
- _status.ima_ch[0].stepIndex += stepAdjust(code);
- _status.ima_ch[0].stepIndex = CLIP<int32>(_status.ima_ch[0].stepIndex, 0, ARRAYSIZE(okiStepSize) - 1);
-
- // * 16 effectively converts 12-bit input to 16-bit output
- return samp * 16;
-}
-
-
-#pragma mark -
-
-
-class Ima_ADPCMStream : public ADPCMStream {
-protected:
- int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
-
-public:
- Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- memset(&_status, 0, sizeof(_status));
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Ima_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- byte data;
-
- assert(numSamples % 2 == 0);
-
- 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);
- }
- return samples;
-}
-
-#pragma mark -
-
-
-class Apple_ADPCMStream : public Ima_ADPCMStream {
-protected:
- // Apple QuickTime IMA ADPCM
- int32 _streamPos[2];
- int16 _buffer[2][2];
- uint8 _chunkPos[2];
-
- void reset() {
- Ima_ADPCMStream::reset();
- _chunkPos[0] = 0;
- _chunkPos[1] = 0;
- _streamPos[0] = 0;
- _streamPos[1] = _blockAlign;
- }
-
-public:
- Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- _chunkPos[0] = 0;
- _chunkPos[1] = 0;
- _streamPos[0] = 0;
- _streamPos[1] = _blockAlign;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-};
-
-int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- // Need to write at least one samples per channel
- assert((numSamples % _channels) == 0);
-
- // Current sample positions
- int samples[2] = { 0, 0};
-
- // Number of samples per channel
- int chanSamples = numSamples / _channels;
-
- for (int i = 0; i < _channels; i++) {
- _stream->seek(_streamPos[i]);
-
- while ((samples[i] < chanSamples) &&
- // Last byte read and a new one needed
- !((_stream->eos() || (_stream->pos() >= _endpos)) && (_chunkPos[i] == 0))) {
-
- if (_blockPos[i] == _blockAlign) {
- // 2 byte header per block
- uint16 temp = _stream->readUint16BE();
-
- // First 9 bits are the upper bits of the predictor
- _status.ima_ch[i].last = (int16) (temp & 0xFF80);
- // Lower 7 bits are the step index
- _status.ima_ch[i].stepIndex = temp & 0x007F;
-
- // Clip the step index
- _status.ima_ch[i].stepIndex = CLIP<int32>(_status.ima_ch[i].stepIndex, 0, 88);
-
- _blockPos[i] = 2;
- }
-
- if (_chunkPos[i] == 0) {
- // Decode data
- byte data = _stream->readByte();
- _buffer[i][0] = decodeIMA(data & 0x0F, i);
- _buffer[i][1] = decodeIMA(data >> 4, i);
- }
-
- // The original is interleaved block-wise, we want it sample-wise
- buffer[_channels * samples[i] + i] = _buffer[i][_chunkPos[i]];
-
- if (++_chunkPos[i] > 1) {
- // We're about to decode the next byte, so advance the block position
- _chunkPos[i] = 0;
- _blockPos[i]++;
- }
-
- samples[i]++;
-
- if (_channels == 2)
- if (_blockPos[i] == _blockAlign)
- // We're at the end of the block.
- // Since the channels are interleaved, skip the next block
- _stream->skip(MIN<uint32>(_blockAlign, _endpos - _stream->pos()));
-
- _streamPos[i] = _stream->pos();
- }
- }
-
- return samples[0] + samples[1];
-}
-
-#pragma mark -
-
-
-class MSIma_ADPCMStream : public Ima_ADPCMStream {
-public:
- MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign, bool invertSamples = false)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign), _invertSamples(invertSamples) {
- if (blockAlign == 0)
- error("ADPCMStream(): blockAlign isn't specified for MS IMA ADPCM");
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples) {
- if (_channels == 1)
- return readBufferMSIMA1(buffer, numSamples);
- else
- return readBufferMSIMA2(buffer, numSamples);
- }
-
- int readBufferMSIMA1(int16 *buffer, const int numSamples);
- int readBufferMSIMA2(int16 *buffer, const int numSamples);
-
-private:
- bool _invertSamples; // Some implementations invert the way samples are decoded
-};
-
-int MSIma_ADPCMStream::readBufferMSIMA1(int16 *buffer, const int numSamples) {
- int samples = 0;
- byte data;
-
- assert(numSamples % 2 == 0);
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- // read block header
- _status.ima_ch[0].last = _stream->readSint16LE();
- _status.ima_ch[0].stepIndex = _stream->readSint16LE();
- _blockPos[0] = 4;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- _blockPos[0]++;
- buffer[samples] = decodeIMA(_invertSamples ? (data >> 4) & 0x0f : data & 0x0f);
- buffer[samples + 1] = decodeIMA(_invertSamples ? data & 0x0f : (data >> 4) & 0x0f);
- }
- }
- return samples;
-}
-
-
-// Microsoft as usual tries to implement it differently. This method
-// is used for stereo data.
-int MSIma_ADPCMStream::readBufferMSIMA2(int16 *buffer, const int numSamples) {
- int samples;
- uint32 data;
- int nibble;
- byte k;
-
- // TODO: Currently this implementation only supports
- // reading a multiple of 16 samples at once. We might
- // consider changing that so it could read an arbitrary
- // sample pair count.
- assert(numSamples % 16 == 0);
-
- for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos;) {
- for (int channel = 0; channel < 2; channel++) {
- data = _stream->readUint32LE();
-
- for (nibble = 0; nibble < 8; nibble++) {
- k = ((data & 0xf0000000) >> 28);
- buffer[samples + channel + nibble * 2] = decodeIMA(k);
- data <<= 4;
- }
- }
- samples += 16;
- }
- return samples;
-}
-
-
-#pragma mark -
-
-
-static const int MSADPCMAdaptCoeff1[] = {
- 256, 512, 0, 192, 240, 460, 392
-};
-
-static const int MSADPCMAdaptCoeff2[] = {
- 0, -256, 0, 64, 0, -208, -232
-};
-
-static const int MSADPCMAdaptationTable[] = {
- 230, 230, 230, 230, 307, 409, 512, 614,
- 768, 614, 512, 409, 307, 230, 230, 230
-};
-
-
-class MS_ADPCMStream : public ADPCMStream {
-protected:
- struct ADPCMChannelStatus {
- byte predictor;
- int16 delta;
- int16 coeff1;
- int16 coeff2;
- int16 sample1;
- int16 sample2;
- };
-
- struct {
- // MS ADPCM
- ADPCMChannelStatus ch[2];
- } _status;
-
- void reset() {
- ADPCMStream::reset();
- memset(&_status, 0, sizeof(_status));
- }
-
-public:
- MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- if (blockAlign == 0)
- error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
- memset(&_status, 0, sizeof(_status));
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-protected:
- int16 decodeMS(ADPCMChannelStatus *c, byte);
-};
-
-int16 MS_ADPCMStream::decodeMS(ADPCMChannelStatus *c, byte code) {
- int32 predictor;
-
- predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 256;
- predictor += (signed)((code & 0x08) ? (code - 0x10) : (code)) * c->delta;
-
- predictor = CLIP<int32>(predictor, -32768, 32767);
-
- c->sample2 = c->sample1;
- c->sample1 = predictor;
- c->delta = (MSADPCMAdaptationTable[(int)code] * c->delta) >> 8;
-
- if (c->delta < 16)
- c->delta = 16;
-
- return (int16)predictor;
-}
-
-int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- byte data;
- int i = 0;
-
- samples = 0;
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- // read block header
- for (i = 0; i < _channels; i++) {
- _status.ch[i].predictor = CLIP(_stream->readByte(), (byte)0, (byte)6);
- _status.ch[i].coeff1 = MSADPCMAdaptCoeff1[_status.ch[i].predictor];
- _status.ch[i].coeff2 = MSADPCMAdaptCoeff2[_status.ch[i].predictor];
- }
-
- for (i = 0; i < _channels; i++)
- _status.ch[i].delta = _stream->readSint16LE();
-
- for (i = 0; i < _channels; i++)
- _status.ch[i].sample1 = _stream->readSint16LE();
-
- for (i = 0; i < _channels; i++)
- buffer[samples++] = _status.ch[i].sample2 = _stream->readSint16LE();
-
- for (i = 0; i < _channels; i++)
- buffer[samples++] = _status.ch[i].sample1;
-
- _blockPos[0] = _channels * 7;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
- data = _stream->readByte();
- _blockPos[0]++;
- buffer[samples] = decodeMS(&_status.ch[0], (data >> 4) & 0x0f);
- buffer[samples + 1] = decodeMS(&_status.ch[_channels - 1], data & 0x0f);
- }
- }
-
- return samples;
-}
-
-
-
-#pragma mark -
-
-
-class Tinsel_ADPCMStream : public ADPCMStream {
-protected:
- struct {
- // Tinsel
- double predictor;
- double K0, K1;
- double d0, d1;
- } _status;
-
- void reset() {
- ADPCMStream::reset();
- memset(&_status, 0, sizeof(_status));
- }
-
- int16 decodeTinsel(int16, double);
- void readBufferTinselHeader();
-
-public:
- Tinsel_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
-
- if (blockAlign == 0)
- error("Tinsel_ADPCMStream(): blockAlign isn't specified");
-
- if (channels != 1)
- error("Tinsel_ADPCMStream(): Tinsel ADPCM only supports mono");
-
- memset(&_status, 0, sizeof(_status));
- }
-
-};
-
-static const double TinselFilterTable[4][2] = {
- {0, 0 },
- {0.9375, 0},
- {1.796875, -0.8125},
- {1.53125, -0.859375}
-};
-
-void Tinsel_ADPCMStream::readBufferTinselHeader() {
- uint8 start = _stream->readByte();
- uint8 filterVal = (start & 0xC0) >> 6;
-
- if ((start & 0x20) != 0) {
- //Lower 6 bit are negative
-
- // Negate
- start = ~(start | 0xC0) + 1;
-
- _status.predictor = 1 << start;
- } else {
- // Lower 6 bit are positive
-
- // Truncate
- start &= 0x1F;
-
- _status.predictor = ((double) 1.0) / (1 << start);
- }
-
- _status.K0 = TinselFilterTable[filterVal][0];
- _status.K1 = TinselFilterTable[filterVal][1];
-}
-
-int16 Tinsel_ADPCMStream::decodeTinsel(int16 code, double eVal) {
- double sample;
-
- sample = (double) code;
- sample *= eVal * _status.predictor;
- sample += (_status.d0 * _status.K0) + (_status.d1 * _status.K1);
-
- _status.d1 = _status.d0;
- _status.d0 = sample;
-
- return (int16) CLIP<double>(sample, -32768.0, 32767.0);
-}
-
-class Tinsel4_ADPCMStream : public Tinsel_ADPCMStream {
-public:
- Tinsel4_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel4_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- uint16 data;
- const double eVal = 1.142822265;
-
- samples = 0;
-
- assert(numSamples % 2 == 0);
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2, _blockPos[0]++) {
- // Read 1 byte = 8 bits = two 4 bit blocks
- data = _stream->readByte();
- buffer[samples] = decodeTinsel((data << 8) & 0xF000, eVal);
- buffer[samples+1] = decodeTinsel((data << 12) & 0xF000, eVal);
- }
- }
-
- return samples;
-}
-
-class Tinsel6_ADPCMStream : public Tinsel_ADPCMStream {
-protected:
- uint8 _chunkPos;
- uint16 _chunkData;
-
- void reset() {
- ADPCMStream::reset();
- _chunkPos = 0;
- _chunkData = 0;
- }
-
-public:
- Tinsel6_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
- _chunkPos = 0;
- _chunkData = 0;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel6_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- const double eVal = 1.032226562;
-
- samples = 0;
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- _chunkPos = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _chunkPos = (_chunkPos + 1) % 4) {
-
- switch (_chunkPos) {
- case 0:
- _chunkData = _stream->readByte();
- buffer[samples] = decodeTinsel((_chunkData << 8) & 0xFC00, eVal);
- break;
- case 1:
- _chunkData = (_chunkData << 8) | (_stream->readByte());
- buffer[samples] = decodeTinsel((_chunkData << 6) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- case 2:
- _chunkData = (_chunkData << 8) | (_stream->readByte());
- buffer[samples] = decodeTinsel((_chunkData << 4) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- case 3:
- _chunkData = (_chunkData << 8);
- buffer[samples] = decodeTinsel((_chunkData << 2) & 0xFC00, eVal);
- _blockPos[0]++;
- break;
- }
-
- }
-
- }
-
- return samples;
-}
-
-class Tinsel8_ADPCMStream : public Tinsel_ADPCMStream {
-public:
- Tinsel8_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-};
-
-int Tinsel8_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples;
- byte data;
- const double eVal = 1.007843258;
-
- samples = 0;
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if (_blockPos[0] == _blockAlign) {
- readBufferTinselHeader();
- _blockPos[0] = 0;
- }
-
- for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _blockPos[0]++) {
- // Read 1 byte = 8 bits = one 8 bit block
- data = _stream->readByte();
- buffer[samples] = decodeTinsel(data << 8, eVal);
- }
- }
-
- return samples;
-}
-
-
-#pragma mark -
-
-// Duck DK3 IMA ADPCM Decoder
-// Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
-
-class DK3_ADPCMStream : public Ima_ADPCMStream {
-protected:
-
- void reset() {
- Ima_ADPCMStream::reset();
- _topNibble = false;
- }
-
-public:
- DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
- : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
-
- // DK3 only works as a stereo stream
- assert(channels == 2);
- _topNibble = false;
- }
-
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-private:
- byte _nibble, _lastByte;
- bool _topNibble;
-};
-
-#define DK3_READ_NIBBLE() \
-do { \
- if (_topNibble) { \
- _nibble = _lastByte >> 4; \
- _topNibble = false; \
- } else { \
- if (_stream->pos() >= _endpos) \
- break; \
- if ((_stream->pos() % _blockAlign) == 0) \
- continue; \
- _lastByte = _stream->readByte(); \
- _nibble = _lastByte & 0xf; \
- _topNibble = true; \
- } \
-} while (0)
-
-
-int DK3_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples = 0;
-
- assert((numSamples % 4) == 0);
-
- while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
- if ((_stream->pos() % _blockAlign) == 0) {
- _stream->readUint16LE(); // Unknown
- uint16 rate = _stream->readUint16LE(); // Copy of rate
- _stream->skip(6); // Unknown
- // Get predictor for both sum/diff channels
- _status.ima_ch[0].last = _stream->readSint16LE();
- _status.ima_ch[1].last = _stream->readSint16LE();
- // Get index for both sum/diff channels
- _status.ima_ch[0].stepIndex = _stream->readByte();
- _status.ima_ch[1].stepIndex = _stream->readByte();
-
- if (_stream->eos())
- break;
-
- // Sanity check
- assert(rate == getRate());
- }
-
- DK3_READ_NIBBLE();
- decodeIMA(_nibble, 0);
-
- DK3_READ_NIBBLE();
- decodeIMA(_nibble, 1);
-
- buffer[samples++] = _status.ima_ch[0].last + _status.ima_ch[1].last;
- buffer[samples++] = _status.ima_ch[0].last - _status.ima_ch[1].last;
-
- DK3_READ_NIBBLE();
- decodeIMA(_nibble, 0);
-
- buffer[samples++] = _status.ima_ch[0].last + _status.ima_ch[1].last;
- buffer[samples++] = _status.ima_ch[0].last - _status.ima_ch[1].last;
- }
-
- return samples;
-}
-
-
-#pragma mark -
-
-
-// adjust the step for use on the next sample.
-int16 ADPCMStream::stepAdjust(byte code) {
- static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
-
- return adjusts[code & 0x07];
-}
-
-static const uint16 imaStepTable[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14,
- 16, 17, 19, 21, 23, 25, 28, 31,
- 34, 37, 41, 45, 50, 55, 60, 66,
- 73, 80, 88, 97, 107, 118, 130, 143,
- 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658,
- 724, 796, 876, 963, 1060, 1166, 1282, 1411,
- 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
- 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
- 7132, 7845, 8630, 9493,10442,11487,12635,13899,
- 15289,16818,18500,20350,22385,24623,27086,29794,
- 32767
-};
-
-int16 Ima_ADPCMStream::decodeIMA(byte code, int channel) {
- int32 E = (2 * (code & 0x7) + 1) * imaStepTable[_status.ima_ch[channel].stepIndex] / 8;
- int32 diff = (code & 0x08) ? -E : E;
- int32 samp = CLIP<int32>(_status.ima_ch[channel].last + diff, -32768, 32767);
-
- _status.ima_ch[channel].last = samp;
- _status.ima_ch[channel].stepIndex += stepAdjust(code);
- _status.ima_ch[channel].stepIndex = CLIP<int32>(_status.ima_ch[channel].stepIndex, 0, ARRAYSIZE(imaStepTable) - 1);
-
- return samp;
-}
-
-RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, typesADPCM type, int rate, int channels, uint32 blockAlign) {
- // If size is 0, report the entire size of the stream
- if (!size)
- size = stream->size();
-
- switch (type) {
- case kADPCMOki:
- return new Oki_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMMSIma:
- return new MSIma_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMMSImaLastExpress:
- return new MSIma_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign, true);
- case kADPCMMS:
- return new MS_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel4:
- return new Tinsel4_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel6:
- return new Tinsel6_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMTinsel8:
- return new Tinsel8_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMIma:
- return new Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMApple:
- return new Apple_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- case kADPCMDK3:
- return new DK3_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
- default:
- error("Unsupported ADPCM encoding");
- break;
- }
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/adpcm.h b/sound/decoders/adpcm.h
deleted file mode 100644
index 38ec870a27..0000000000
--- a/sound/decoders/adpcm.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - lastexpress
- * - mohawk
- * - saga
- * - scumm
- * - tinsel
- */
-
-#ifndef SOUND_ADPCM_H
-#define SOUND_ADPCM_H
-
-#include "common/scummsys.h"
-#include "common/stream.h"
-
-
-namespace Audio {
-
-class AudioStream;
-class RewindableAudioStream;
-
-// There are several types of ADPCM encoding, only some are supported here
-// For all the different encodings, refer to:
-// http://wiki.multimedia.cx/index.php?title=Category:ADPCM_Audio_Codecs
-// Usually, if the audio stream we're trying to play has the FourCC header
-// string intact, it's easy to discern which encoding is used
-enum typesADPCM {
- kADPCMOki, // Dialogic/Oki ADPCM (aka VOX)
- kADPCMMSIma, // Microsoft IMA ADPCM
- kADPCMMSImaLastExpress, // Microsoft IMA ADPCM (with inverted samples)
- kADPCMMS, // Microsoft ADPCM
- kADPCMTinsel4, // 4-bit ADPCM used by the Tinsel engine
- kADPCMTinsel6, // 6-bit ADPCM used by the Tinsel engine
- kADPCMTinsel8, // 8-bit ADPCM used by the Tinsel engine
- kADPCMIma, // Standard IMA ADPCM
- kADPCMApple, // Apple QuickTime IMA ADPCM
- kADPCMDK3 // Duck DK3 IMA ADPCM
-};
-
-/**
- * Takes an input stream containing ADPCM compressed sound data and creates
- * an RewindableAudioStream from that.
- *
- * @param stream the SeekableReadStream from which to read the ADPCM data
- * @param disposeAfterUse whether to delete the stream after use
- * @param size how many bytes to read from the stream (0 = all)
- * @param type the compression type used
- * @param rate the sampling rate
- * @param channels the number of channels
- * @param blockAlign block alignment ???
- * @return a new RewindableAudioStream, or NULL, if an error occurred
- */
-RewindableAudioStream *makeADPCMStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse,
- uint32 size, typesADPCM type,
- int rate = 22050,
- int channels = 2,
- uint32 blockAlign = 0);
-
-} // End of namespace Audio
-
-#endif
diff --git a/sound/decoders/aiff.cpp b/sound/decoders/aiff.cpp
deleted file mode 100644
index ce8c6ad32c..0000000000
--- a/sound/decoders/aiff.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * The code in this file is based on information found at
- * http://www.borg.com/~jglatt/tech/aiff.htm
- *
- * We currently only implement uncompressed AIFF. If we ever need AIFF-C, SoX
- * (http://sox.sourceforge.net) may be a good place to start from.
- */
-
-#include "common/endian.h"
-#include "common/util.h"
-#include "common/stream.h"
-
-#include "sound/decoders/aiff.h"
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/raw.h"
-
-namespace Audio {
-
-uint32 readExtended(Common::SeekableReadStream &stream) {
- // The sample rate is stored as an "80 bit IEEE Standard 754 floating
- // point number (Standard Apple Numeric Environment [SANE] data type
- // Extended).
-
- byte buf[10];
- uint32 mantissa;
- uint32 last = 0;
- byte exp;
-
- stream.read(buf, 10);
- mantissa = READ_BE_UINT32(buf + 2);
- exp = 30 - buf[1];
-
- while (exp--) {
- last = mantissa;
- mantissa >>= 1;
- }
-
- if (last & 0x00000001)
- mantissa++;
-
- return mantissa;
-}
-
-bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags) {
- byte buf[4];
-
- stream.read(buf, 4);
- if (memcmp(buf, "FORM", 4) != 0) {
- warning("loadAIFFFromStream: No 'FORM' header");
- return false;
- }
-
- stream.readUint32BE();
-
- // This could be AIFC, but we don't handle that case.
-
- stream.read(buf, 4);
- if (memcmp(buf, "AIFF", 4) != 0) {
- warning("loadAIFFFromStream: No 'AIFF' header");
- return false;
- }
-
- // From here on, we only care about the COMM and SSND chunks, which are
- // the only required chunks.
-
- bool foundCOMM = false;
- bool foundSSND = false;
-
- uint16 numChannels = 0, bitsPerSample = 0;
- uint32 numSampleFrames = 0, offset = 0, blockSize = 0, soundOffset = 0;
-
- while (!(foundCOMM && foundSSND) && !stream.err() && !stream.eos()) {
- uint32 length, pos;
-
- stream.read(buf, 4);
- length = stream.readUint32BE();
- pos = stream.pos();
-
- if (memcmp(buf, "COMM", 4) == 0) {
- foundCOMM = true;
- numChannels = stream.readUint16BE();
- numSampleFrames = stream.readUint32BE();
- bitsPerSample = stream.readUint16BE();
- rate = readExtended(stream);
- size = numSampleFrames * numChannels * (bitsPerSample / 8);
- } else if (memcmp(buf, "SSND", 4) == 0) {
- foundSSND = true;
- offset = stream.readUint32BE();
- blockSize = stream.readUint32BE();
- soundOffset = stream.pos();
- }
-
- stream.seek(pos + length);
- }
-
- if (!foundCOMM) {
- warning("loadAIFFFromStream: Cound not find 'COMM' chunk");
- return false;
- }
-
- if (!foundSSND) {
- warning("loadAIFFFromStream: Cound not find 'SSND' chunk");
- return false;
- }
-
- // We only implement a subset of the AIFF standard.
-
- if (numChannels < 1 || numChannels > 2) {
- warning("loadAIFFFromStream: Only 1 or 2 channels are supported, not %d", numChannels);
- return false;
- }
-
- if (bitsPerSample != 8 && bitsPerSample != 16) {
- warning("loadAIFFFromStream: Only 8 or 16 bits per sample are supported, not %d", bitsPerSample);
- return false;
- }
-
- if (offset != 0 || blockSize != 0) {
- warning("loadAIFFFromStream: Block-aligned data is not supported");
- return false;
- }
-
- // Samples are always signed, and big endian.
-
- flags = 0;
- if (bitsPerSample == 16)
- flags |= Audio::FLAG_16BITS;
- if (numChannels == 2)
- flags |= Audio::FLAG_STEREO;
-
- stream.seek(soundOffset);
-
- // Stream now points at the sample data
-
- return true;
-}
-
-SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse) {
- int size, rate;
- byte *data, flags;
-
- if (!loadAIFFFromStream(*stream, size, rate, flags)) {
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
- return 0;
- }
-
- data = (byte *)malloc(size);
- assert(data);
- stream->read(data, size);
-
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
-
- // Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES.
- return makeRawStream(data, size, rate, flags);
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/aiff.h b/sound/decoders/aiff.h
deleted file mode 100644
index 06c56ecd38..0000000000
--- a/sound/decoders/aiff.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - saga
- * - sci
- * - sword1
- */
-
-#ifndef SOUND_AIFF_H
-#define SOUND_AIFF_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-namespace Common { class SeekableReadStream; }
-
-namespace Audio {
-
-class SeekableAudioStream;
-
-/**
- * Try to load an AIFF from the given seekable stream. Returns true if
- * successful. In that case, the stream's seek position will be set to the
- * start of the audio data, and size, rate and flags contain information
- * necessary for playback. Currently this function only supports uncompressed
- * raw PCM data as well as IMA ADPCM.
- */
-extern bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags);
-
-/**
- * Try to load an AIFF from the given seekable stream and create an AudioStream
- * from that data.
- *
- * This function uses loadAIFFFromStream() internally.
- *
- * @param stream the SeekableReadStream from which to read the AIFF data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occurred
- */
-SeekableAudioStream *makeAIFFStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif
diff --git a/sound/decoders/flac.cpp b/sound/decoders/flac.cpp
deleted file mode 100644
index 080141f224..0000000000
--- a/sound/decoders/flac.cpp
+++ /dev/null
@@ -1,745 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-// Disable symbol overrides for FILE as that is used in FLAC headers
-#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
-
-#include "sound/decoders/flac.h"
-
-#ifdef USE_FLAC
-
-#include "common/debug.h"
-#include "common/stream.h"
-#include "common/util.h"
-
-#include "sound/audiostream.h"
-
-#define FLAC__NO_DLL // that MS-magic gave me headaches - just link the library you like
-#include <FLAC/export.h>
-
-
-// check if we have FLAC >= 1.1.3; LEGACY_FLAC code can be removed once FLAC-1.1.3 propagates everywhere
-#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8
-#define LEGACY_FLAC
-#else
-#undef LEGACY_FLAC
-#endif
-
-
-#ifdef LEGACY_FLAC
-
-// Before FLAC 1.1.3, we needed to use the stream decoder API.
-#include <FLAC/seekable_stream_decoder.h>
-typedef uint FLAC_size_t;
-
-#else
-
-// With FLAC 1.1.3, the stream decoder API was merged into the regular
-// stream API. In order to stay compatible with older FLAC versions, we
-// simply add some typedefs and #ifdefs to map between the old and new API.
-// We use the typedefs (instead of only #defines) in order to somewhat
-// improve the readability of the code.
-
-#include <FLAC/stream_decoder.h>
-typedef size_t FLAC_size_t;
-// Add aliases for the old names
-typedef FLAC__StreamDecoderState FLAC__SeekableStreamDecoderState;
-typedef FLAC__StreamDecoderReadStatus FLAC__SeekableStreamDecoderReadStatus;
-typedef FLAC__StreamDecoderSeekStatus FLAC__SeekableStreamDecoderSeekStatus;
-typedef FLAC__StreamDecoderTellStatus FLAC__SeekableStreamDecoderTellStatus;
-typedef FLAC__StreamDecoderLengthStatus FLAC__SeekableStreamDecoderLengthStatus;
-typedef FLAC__StreamDecoder FLAC__SeekableStreamDecoder;
-
-#endif
-
-
-namespace Audio {
-
-#pragma mark -
-#pragma mark --- FLAC stream ---
-#pragma mark -
-
-static const uint MAX_OUTPUT_CHANNELS = 2;
-
-
-class FLACStream : public SeekableAudioStream {
-protected:
- Common::SeekableReadStream *_inStream;
- bool _disposeAfterUse;
-
- ::FLAC__SeekableStreamDecoder *_decoder;
-
- /** Header of the stream */
- FLAC__StreamMetadata_StreamInfo _streaminfo;
-
- /** index + 1(!) of the last sample to be played */
- FLAC__uint64 _lastSample;
-
- /** total play time */
- Timestamp _length;
-
- /** true if the last sample was decoded from the FLAC-API - there might still be data in the buffer */
- bool _lastSampleWritten;
-
- typedef int16 SampleType;
- enum { BUFTYPE_BITS = 16 };
-
- enum {
- // Maximal buffer size. According to the FLAC format specification, the block size is
- // a 16 bit value (in fact it seems the maximal block size is 32768, but we play it safe).
- BUFFER_SIZE = 65536
- };
-
- struct {
- SampleType bufData[BUFFER_SIZE];
- SampleType *bufReadPos;
- uint bufFill;
- } _sampleCache;
-
- SampleType *_outBuffer;
- uint _requestedSamples;
-
- typedef void (*PFCONVERTBUFFERS)(SampleType*, const FLAC__int32*[], uint, const uint, const uint8);
- PFCONVERTBUFFERS _methodConvertBuffers;
-
-
-public:
- FLACStream(Common::SeekableReadStream *inStream, bool dispose);
- virtual ~FLACStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool isStereo() const { return _streaminfo.channels >= 2; }
- int getRate() const { return _streaminfo.sample_rate; }
- bool endOfData() const {
- // End of data is reached if there either is no valid stream data available,
- // or if we reached the last sample and completely emptied the sample cache.
- return _streaminfo.channels == 0 || (_lastSampleWritten && _sampleCache.bufFill == 0);
- }
-
- bool seek(const Timestamp &where);
- Timestamp getLength() const { return _length; }
-
- bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; }
-protected:
- uint getChannels() const { return MIN<uint>(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
-
- bool allocateBuffer(uint minSamples);
-
- inline FLAC__StreamDecoderState getStreamDecoderState() const;
-
- inline bool processSingleBlock();
- inline bool processUntilEndOfMetadata();
- bool seekAbsolute(FLAC__uint64 sample);
-
- inline ::FLAC__SeekableStreamDecoderReadStatus callbackRead(FLAC__byte buffer[], FLAC_size_t *bytes);
- inline ::FLAC__SeekableStreamDecoderSeekStatus callbackSeek(FLAC__uint64 absoluteByteOffset);
- inline ::FLAC__SeekableStreamDecoderTellStatus callbackTell(FLAC__uint64 *absoluteByteOffset);
- inline ::FLAC__SeekableStreamDecoderLengthStatus callbackLength(FLAC__uint64 *streamLength);
- inline bool callbackEOF();
- inline ::FLAC__StreamDecoderWriteStatus callbackWrite(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
- inline void callbackMetadata(const ::FLAC__StreamMetadata *metadata);
- inline void callbackError(::FLAC__StreamDecoderErrorStatus status);
-
-private:
- static ::FLAC__SeekableStreamDecoderReadStatus callWrapRead(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], FLAC_size_t *bytes, void *clientData);
- static ::FLAC__SeekableStreamDecoderSeekStatus callWrapSeek(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absoluteByteOffset, void *clientData);
- static ::FLAC__SeekableStreamDecoderTellStatus callWrapTell(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absoluteByteOffset, void *clientData);
- static ::FLAC__SeekableStreamDecoderLengthStatus callWrapLength(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *streamLength, void *clientData);
- static FLAC__bool callWrapEOF(const ::FLAC__SeekableStreamDecoder *decoder, void *clientData);
- static ::FLAC__StreamDecoderWriteStatus callWrapWrite(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *clientData);
- static void callWrapMetadata(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *clientData);
- static void callWrapError(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *clientData);
-
- void setBestConvertBufferMethod();
- static void convertBuffersGeneric(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
- static void convertBuffersStereoNS(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
- static void convertBuffersStereo8Bit(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
- static void convertBuffersMonoNS(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
- static void convertBuffersMono8Bit(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits);
-};
-
-FLACStream::FLACStream(Common::SeekableReadStream *inStream, bool dispose)
-#ifdef LEGACY_FLAC
- : _decoder(::FLAC__seekable_stream_decoder_new()),
-#else
- : _decoder(::FLAC__stream_decoder_new()),
-#endif
- _inStream(inStream),
- _disposeAfterUse(dispose),
- _length(0, 1000), _lastSample(0),
- _outBuffer(NULL), _requestedSamples(0), _lastSampleWritten(false),
- _methodConvertBuffers(&FLACStream::convertBuffersGeneric)
-{
- assert(_inStream);
- memset(&_streaminfo, 0, sizeof(_streaminfo));
-
- _sampleCache.bufReadPos = NULL;
- _sampleCache.bufFill = 0;
-
- _methodConvertBuffers = &FLACStream::convertBuffersGeneric;
-
- bool success;
-#ifdef LEGACY_FLAC
- ::FLAC__seekable_stream_decoder_set_read_callback(_decoder, &FLACStream::callWrapRead);
- ::FLAC__seekable_stream_decoder_set_seek_callback(_decoder, &FLACStream::callWrapSeek);
- ::FLAC__seekable_stream_decoder_set_tell_callback(_decoder, &FLACStream::callWrapTell);
- ::FLAC__seekable_stream_decoder_set_length_callback(_decoder, &FLACStream::callWrapLength);
- ::FLAC__seekable_stream_decoder_set_eof_callback(_decoder, &FLACStream::callWrapEOF);
- ::FLAC__seekable_stream_decoder_set_write_callback(_decoder, &FLACStream::callWrapWrite);
- ::FLAC__seekable_stream_decoder_set_metadata_callback(_decoder, &FLACStream::callWrapMetadata);
- ::FLAC__seekable_stream_decoder_set_error_callback(_decoder, &FLACStream::callWrapError);
- ::FLAC__seekable_stream_decoder_set_client_data(_decoder, (void*)this);
-
- success = (::FLAC__seekable_stream_decoder_init(_decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK);
-#else
- success = (::FLAC__stream_decoder_init_stream(
- _decoder,
- &FLACStream::callWrapRead,
- &FLACStream::callWrapSeek,
- &FLACStream::callWrapTell,
- &FLACStream::callWrapLength,
- &FLACStream::callWrapEOF,
- &FLACStream::callWrapWrite,
- &FLACStream::callWrapMetadata,
- &FLACStream::callWrapError,
- (void*)this
- ) == FLAC__STREAM_DECODER_INIT_STATUS_OK);
-#endif
- if (success) {
- if (processUntilEndOfMetadata() && _streaminfo.channels > 0) {
- _lastSample = _streaminfo.total_samples + 1;
- _length = Timestamp(0, _lastSample - 1, getRate());
- return; // no error occurred
- }
- }
-
- warning("FLACStream: could not create audio stream");
-}
-
-FLACStream::~FLACStream() {
- if (_decoder != NULL) {
-#ifdef LEGACY_FLAC
- (void) ::FLAC__seekable_stream_decoder_finish(_decoder);
- ::FLAC__seekable_stream_decoder_delete(_decoder);
-#else
- (void) ::FLAC__stream_decoder_finish(_decoder);
- ::FLAC__stream_decoder_delete(_decoder);
-#endif
- }
- if (_disposeAfterUse)
- delete _inStream;
-}
-
-inline FLAC__StreamDecoderState FLACStream::getStreamDecoderState() const {
- assert(_decoder != NULL);
-#ifdef LEGACY_FLAC
- return ::FLAC__seekable_stream_decoder_get_stream_decoder_state(_decoder);
-#else
- return ::FLAC__stream_decoder_get_state(_decoder);
-#endif
-}
-
-inline bool FLACStream::processSingleBlock() {
- assert(_decoder != NULL);
-#ifdef LEGACY_FLAC
- return 0 != ::FLAC__seekable_stream_decoder_process_single(_decoder);
-#else
- return 0 != ::FLAC__stream_decoder_process_single(_decoder);
-#endif
-}
-
-inline bool FLACStream::processUntilEndOfMetadata() {
- assert(_decoder != NULL);
-#ifdef LEGACY_FLAC
- return 0 != ::FLAC__seekable_stream_decoder_process_until_end_of_metadata(_decoder);
-#else
- return 0 != ::FLAC__stream_decoder_process_until_end_of_metadata(_decoder);
-#endif
-}
-
-bool FLACStream::seekAbsolute(FLAC__uint64 sample) {
- assert(_decoder != NULL);
-#ifdef LEGACY_FLAC
- const bool result = (0 != ::FLAC__seekable_stream_decoder_seek_absolute(_decoder, sample));
-#else
- const bool result = (0 != ::FLAC__stream_decoder_seek_absolute(_decoder, sample));
-#endif
- if (result) {
- _lastSampleWritten = (_lastSample != 0 && sample >= _lastSample); // only set if we are SURE
- }
- return result;
-}
-
-bool FLACStream::seek(const Timestamp &where) {
- _sampleCache.bufFill = 0;
- _sampleCache.bufReadPos = NULL;
- // FLAC uses the sample pair number, thus we always use "false" for the isStereo parameter
- // of the convertTimeToStreamPos helper.
- return seekAbsolute((FLAC__uint64)convertTimeToStreamPos(where, getRate(), false).totalNumberOfFrames());
-}
-
-int FLACStream::readBuffer(int16 *buffer, const int numSamples) {
- const uint numChannels = getChannels();
-
- if (numChannels == 0) {
- warning("FLACStream: Stream not successfully initialised, cant playback");
- return -1; // streaminfo wasnt read!
- }
-
- assert(numSamples % numChannels == 0); // must be multiple of channels!
- assert(buffer != NULL);
- assert(_outBuffer == NULL);
- assert(_requestedSamples == 0);
-
- _outBuffer = buffer;
- _requestedSamples = numSamples;
-
- // If there is still data in our buffer from the last time around,
- // copy that first.
- if (_sampleCache.bufFill > 0) {
- assert(_sampleCache.bufReadPos >= _sampleCache.bufData);
- assert(_sampleCache.bufFill % numChannels == 0);
-
- const uint copySamples = MIN((uint)numSamples, _sampleCache.bufFill);
- memcpy(buffer, _sampleCache.bufReadPos, copySamples*sizeof(buffer[0]));
-
- _outBuffer = buffer + copySamples;
- _requestedSamples = numSamples - copySamples;
- _sampleCache.bufReadPos += copySamples;
- _sampleCache.bufFill -= copySamples;
- }
-
- bool decoderOk = true;
-
- FLAC__StreamDecoderState state = getStreamDecoderState();
-
- // Keep poking FLAC to process more samples until we completely satisfied the request
- // respectively until we run out of data.
- while (!_lastSampleWritten && _requestedSamples > 0 && state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) {
- assert(_sampleCache.bufFill == 0);
- assert(_requestedSamples % numChannels == 0);
- processSingleBlock();
- state = getStreamDecoderState();
-
- if (state == FLAC__STREAM_DECODER_END_OF_STREAM)
- _lastSampleWritten = true;
- }
-
- // Error handling
- switch (state) {
- case FLAC__STREAM_DECODER_END_OF_STREAM:
- _lastSampleWritten = true;
- break;
- case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
- break;
- default:
- decoderOk = false;
- warning("FLACStream: An error occurred while decoding. DecoderState is: %s",
- FLAC__StreamDecoderStateString[getStreamDecoderState()]);
- }
-
- // Compute how many samples we actually produced
- const int samples = (int)(_outBuffer - buffer);
- assert(samples % numChannels == 0);
-
- _outBuffer = NULL; // basically unnecessary, only for the purpose of the asserts
- _requestedSamples = 0; // basically unnecessary, only for the purpose of the asserts
-
- return decoderOk ? samples : -1;
-}
-
-inline ::FLAC__SeekableStreamDecoderReadStatus FLACStream::callbackRead(FLAC__byte buffer[], FLAC_size_t *bytes) {
- if (*bytes == 0) {
-#ifdef LEGACY_FLAC
- return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
-#else
- return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
-#endif
- }
-
- const uint32 bytesRead = _inStream->read(buffer, *bytes);
-
- if (bytesRead == 0) {
-#ifdef LEGACY_FLAC
- return _inStream->eos() ? FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK : FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-#else
- return _inStream->eos() ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-#endif
- }
-
- *bytes = static_cast<uint>(bytesRead);
-#ifdef LEGACY_FLAC
- return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-#else
- return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-#endif
-}
-
-void FLACStream::setBestConvertBufferMethod() {
- PFCONVERTBUFFERS tempMethod = &FLACStream::convertBuffersGeneric;
-
- const uint numChannels = getChannels();
- const uint8 numBits = (uint8)_streaminfo.bits_per_sample;
-
- assert(numChannels >= 1);
- assert(numBits >= 4 && numBits <=32);
-
- if (numChannels == 1) {
- if (numBits == 8)
- tempMethod = &FLACStream::convertBuffersMono8Bit;
- if (numBits == BUFTYPE_BITS)
- tempMethod = &FLACStream::convertBuffersMonoNS;
- } else if (numChannels == 2) {
- if (numBits == 8)
- tempMethod = &FLACStream::convertBuffersStereo8Bit;
- if (numBits == BUFTYPE_BITS)
- tempMethod = &FLACStream::convertBuffersStereoNS;
- } /* else ... */
-
- _methodConvertBuffers = tempMethod;
-}
-
-// 1 channel, no scaling
-void FLACStream::convertBuffersMonoNS(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits) {
- assert(numChannels == 1);
- assert(numBits == BUFTYPE_BITS);
-
- FLAC__int32 const* inChannel1 = inChannels[0];
-
- while (numSamples >= 4) {
- bufDestination[0] = static_cast<SampleType>(inChannel1[0]);
- bufDestination[1] = static_cast<SampleType>(inChannel1[1]);
- bufDestination[2] = static_cast<SampleType>(inChannel1[2]);
- bufDestination[3] = static_cast<SampleType>(inChannel1[3]);
- bufDestination += 4;
- inChannel1 += 4;
- numSamples -= 4;
- }
-
- for (; numSamples > 0; --numSamples) {
- *bufDestination++ = static_cast<SampleType>(*inChannel1++);
- }
-
- inChannels[0] = inChannel1;
- assert(numSamples == 0); // dint copy too many samples
-}
-
-// 1 channel, scaling from 8Bit
-void FLACStream::convertBuffersMono8Bit(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits) {
- assert(numChannels == 1);
- assert(numBits == 8);
- assert(8 < BUFTYPE_BITS);
-
- FLAC__int32 const* inChannel1 = inChannels[0];
-
- while (numSamples >= 4) {
- bufDestination[0] = static_cast<SampleType>(inChannel1[0]) << (BUFTYPE_BITS - 8);
- bufDestination[1] = static_cast<SampleType>(inChannel1[1]) << (BUFTYPE_BITS - 8);
- bufDestination[2] = static_cast<SampleType>(inChannel1[2]) << (BUFTYPE_BITS - 8);
- bufDestination[3] = static_cast<SampleType>(inChannel1[3]) << (BUFTYPE_BITS - 8);
- bufDestination += 4;
- inChannel1 += 4;
- numSamples -= 4;
- }
-
- for (; numSamples > 0; --numSamples) {
- *bufDestination++ = static_cast<SampleType>(*inChannel1++) << (BUFTYPE_BITS - 8);
- }
-
- inChannels[0] = inChannel1;
- assert(numSamples == 0); // dint copy too many samples
-}
-
-// 2 channels, no scaling
-void FLACStream::convertBuffersStereoNS(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits) {
- assert(numChannels == 2);
- assert(numBits == BUFTYPE_BITS);
- assert(numSamples % 2 == 0); // must be integral multiply of channels
-
-
- FLAC__int32 const* inChannel1 = inChannels[0]; // Left Channel
- FLAC__int32 const* inChannel2 = inChannels[1]; // Right Channel
-
- while (numSamples >= 2*2) {
- bufDestination[0] = static_cast<SampleType>(inChannel1[0]);
- bufDestination[1] = static_cast<SampleType>(inChannel2[0]);
- bufDestination[2] = static_cast<SampleType>(inChannel1[1]);
- bufDestination[3] = static_cast<SampleType>(inChannel2[1]);
- bufDestination += 2 * 2;
- inChannel1 += 2;
- inChannel2 += 2;
- numSamples -= 2 * 2;
- }
-
- while (numSamples > 0) {
- bufDestination[0] = static_cast<SampleType>(*inChannel1++);
- bufDestination[1] = static_cast<SampleType>(*inChannel2++);
- bufDestination += 2;
- numSamples -= 2;
- }
-
- inChannels[0] = inChannel1;
- inChannels[1] = inChannel2;
- assert(numSamples == 0); // dint copy too many samples
-}
-
-// 2 channels, scaling from 8Bit
-void FLACStream::convertBuffersStereo8Bit(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits) {
- assert(numChannels == 2);
- assert(numBits == 8);
- assert(numSamples % 2 == 0); // must be integral multiply of channels
- assert(8 < BUFTYPE_BITS);
-
- FLAC__int32 const* inChannel1 = inChannels[0]; // Left Channel
- FLAC__int32 const* inChannel2 = inChannels[1]; // Right Channel
-
- while (numSamples >= 2*2) {
- bufDestination[0] = static_cast<SampleType>(inChannel1[0]) << (BUFTYPE_BITS - 8);
- bufDestination[1] = static_cast<SampleType>(inChannel2[0]) << (BUFTYPE_BITS - 8);
- bufDestination[2] = static_cast<SampleType>(inChannel1[1]) << (BUFTYPE_BITS - 8);
- bufDestination[3] = static_cast<SampleType>(inChannel2[1]) << (BUFTYPE_BITS - 8);
- bufDestination += 2 * 2;
- inChannel1 += 2;
- inChannel2 += 2;
- numSamples -= 2 * 2;
- }
-
- while (numSamples > 0) {
- bufDestination[0] = static_cast<SampleType>(*inChannel1++) << (BUFTYPE_BITS - 8);
- bufDestination[1] = static_cast<SampleType>(*inChannel2++) << (BUFTYPE_BITS - 8);
- bufDestination += 2;
- numSamples -= 2;
- }
-
- inChannels[0] = inChannel1;
- inChannels[1] = inChannel2;
- assert(numSamples == 0); // dint copy too many samples
-}
-
-// all Purpose-conversion - slowest of em all
-void FLACStream::convertBuffersGeneric(SampleType* bufDestination, const FLAC__int32 *inChannels[], uint numSamples, const uint numChannels, const uint8 numBits) {
- assert(numSamples % numChannels == 0); // must be integral multiply of channels
-
- if (numBits < BUFTYPE_BITS) {
- const uint8 kPower = (uint8)(BUFTYPE_BITS - numBits);
-
- for (; numSamples > 0; numSamples -= numChannels) {
- for (uint i = 0; i < numChannels; ++i)
- *bufDestination++ = static_cast<SampleType>(*(inChannels[i]++)) << kPower;
- }
- } else if (numBits > BUFTYPE_BITS) {
- const uint8 kPower = (uint8)(numBits - BUFTYPE_BITS);
-
- for (; numSamples > 0; numSamples -= numChannels) {
- for (uint i = 0; i < numChannels; ++i)
- *bufDestination++ = static_cast<SampleType>(*(inChannels[i]++) >> kPower);
- }
- } else {
- for (; numSamples > 0; numSamples -= numChannels) {
- for (uint i = 0; i < numChannels; ++i)
- *bufDestination++ = static_cast<SampleType>(*(inChannels[i]++));
- }
- }
-
- assert(numSamples == 0); // dint copy too many samples
-}
-
-inline ::FLAC__StreamDecoderWriteStatus FLACStream::callbackWrite(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) {
- assert(frame->header.channels == _streaminfo.channels);
- assert(frame->header.sample_rate == _streaminfo.sample_rate);
- assert(frame->header.bits_per_sample == _streaminfo.bits_per_sample);
- assert(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER || _streaminfo.min_blocksize == _streaminfo.max_blocksize);
-
- // We require that either the sample cache is empty, or that no samples were requested
- assert(_sampleCache.bufFill == 0 || _requestedSamples == 0);
-
- uint numSamples = frame->header.blocksize;
- const uint numChannels = getChannels();
- const uint8 numBits = (uint8)_streaminfo.bits_per_sample;
-
- assert(_requestedSamples % numChannels == 0); // must be integral multiply of channels
-
- const FLAC__uint64 firstSampleNumber = (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER) ?
- frame->header.number.sample_number : (static_cast<FLAC__uint64>(frame->header.number.frame_number)) * _streaminfo.max_blocksize;
-
- // Check whether we are about to reach beyond the last sample we are supposed to play.
- if (_lastSample != 0 && firstSampleNumber + numSamples >= _lastSample) {
- numSamples = (uint)(firstSampleNumber >= _lastSample ? 0 : _lastSample - firstSampleNumber);
- _lastSampleWritten = true;
- }
-
- // The value in _requestedSamples counts raw samples, so if there are more than one
- // channel, we have to multiply the number of available sample "pairs" by numChannels
- numSamples *= numChannels;
-
- const FLAC__int32 *inChannels[MAX_OUTPUT_CHANNELS];
- for (uint i = 0; i < numChannels; ++i)
- inChannels[i] = buffer[i];
-
- // write the incoming samples directly into the buffer provided to us by the mixer
- if (_requestedSamples > 0) {
- assert(_requestedSamples % numChannels == 0);
- assert(_outBuffer != NULL);
-
- // Copy & convert the available samples (limited both by how many we have available, and
- // by how many are actually needed).
- const uint copySamples = MIN(_requestedSamples, numSamples);
- (*_methodConvertBuffers)(_outBuffer, inChannels, copySamples, numChannels, numBits);
-
- _requestedSamples -= copySamples;
- numSamples -= copySamples;
- _outBuffer += copySamples;
- }
-
- // Write all remaining samples (i.e. those which didn't fit into the mixer buffer)
- // into the sample cache.
- if (_sampleCache.bufFill == 0)
- _sampleCache.bufReadPos = _sampleCache.bufData;
- const uint cacheSpace = (_sampleCache.bufData + BUFFER_SIZE) - (_sampleCache.bufReadPos + _sampleCache.bufFill);
- assert(numSamples <= cacheSpace);
- (*_methodConvertBuffers)(_sampleCache.bufReadPos + _sampleCache.bufFill, inChannels, numSamples, numChannels, numBits);
-
- _sampleCache.bufFill += numSamples;
-
- return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-}
-
-inline ::FLAC__SeekableStreamDecoderSeekStatus FLACStream::callbackSeek(FLAC__uint64 absoluteByteOffset) {
- _inStream->seek(absoluteByteOffset, SEEK_SET);
- const bool result = (absoluteByteOffset == (FLAC__uint64)_inStream->pos());
-
-#ifdef LEGACY_FLAC
- return result ? FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK : FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-#else
- return result ? FLAC__STREAM_DECODER_SEEK_STATUS_OK : FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
-#endif
-}
-
-inline ::FLAC__SeekableStreamDecoderTellStatus FLACStream::callbackTell(FLAC__uint64 *absoluteByteOffset) {
- *absoluteByteOffset = static_cast<FLAC__uint64>(_inStream->pos());
-#ifdef LEGACY_FLAC
- return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-#else
- return FLAC__STREAM_DECODER_TELL_STATUS_OK;
-#endif
-}
-
-inline ::FLAC__SeekableStreamDecoderLengthStatus FLACStream::callbackLength(FLAC__uint64 *streamLength) {
- *streamLength = static_cast<FLAC__uint64>(_inStream->size());
-#ifdef LEGACY_FLAC
- return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-#else
- return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
-#endif
-}
-
-inline bool FLACStream::callbackEOF() {
- return _inStream->eos();
-}
-
-
-inline void FLACStream::callbackMetadata(const ::FLAC__StreamMetadata *metadata) {
- assert(_decoder != NULL);
- assert(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); // others arent really interesting
-
- _streaminfo = metadata->data.stream_info;
- setBestConvertBufferMethod(); // should be set after getting stream-information. FLAC always parses the info first
-}
-inline void FLACStream::callbackError(::FLAC__StreamDecoderErrorStatus status) {
- // some of these are non-critical-Errors
- debug(1, "FLACStream: An error occurred while decoding. DecoderState is: %s",
- FLAC__StreamDecoderErrorStatusString[status]);
-}
-
-/* Static Callback Wrappers */
-::FLAC__SeekableStreamDecoderReadStatus FLACStream::callWrapRead(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], FLAC_size_t *bytes, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackRead(buffer, bytes);
-}
-
-::FLAC__SeekableStreamDecoderSeekStatus FLACStream::callWrapSeek(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absoluteByteOffset, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackSeek(absoluteByteOffset);
-}
-
-::FLAC__SeekableStreamDecoderTellStatus FLACStream::callWrapTell(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absoluteByteOffset, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackTell(absoluteByteOffset);
-}
-
-::FLAC__SeekableStreamDecoderLengthStatus FLACStream::callWrapLength(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *streamLength, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackLength(streamLength);
-}
-
-FLAC__bool FLACStream::callWrapEOF(const ::FLAC__SeekableStreamDecoder *decoder, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackEOF();
-}
-
-::FLAC__StreamDecoderWriteStatus FLACStream::callWrapWrite(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- return instance->callbackWrite(frame, buffer);
-}
-
-void FLACStream::callWrapMetadata(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- instance->callbackMetadata(metadata);
-}
-
-void FLACStream::callWrapError(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *clientData) {
- FLACStream *instance = (FLACStream *)clientData;
- assert(0 != instance);
- instance->callbackError(status);
-}
-
-
-#pragma mark -
-#pragma mark --- FLAC factory functions ---
-#pragma mark -
-
-SeekableAudioStream *makeFLACStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse) {
- SeekableAudioStream *s = new FLACStream(stream, disposeAfterUse);
- if (s && s->endOfData()) {
- delete s;
- return 0;
- } else {
- return s;
- }
-}
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_FLAC
diff --git a/sound/decoders/flac.h b/sound/decoders/flac.h
deleted file mode 100644
index 17f95ec1fb..0000000000
--- a/sound/decoders/flac.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - draci
- * - kyra
- * - m4
- * - queen
- * - saga
- * - sci
- * - scumm
- * - sword1
- * - sword2
- * - touche
- * - tucker
- */
-
-#ifndef SOUND_FLAC_H
-#define SOUND_FLAC_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-#ifdef USE_FLAC
-
-namespace Common {
- class SeekableReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-/**
- * Create a new SeekableAudioStream from the FLAC data in the given stream.
- * Allows for seeking (which is why we require a SeekableReadStream).
- *
- * @param stream the SeekableReadStream from which to read the FLAC data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occurred
- */
-SeekableAudioStream *makeFLACStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_FLAC
-#endif // #ifndef SOUND_FLAC_H
diff --git a/sound/decoders/iff_sound.cpp b/sound/decoders/iff_sound.cpp
deleted file mode 100644
index 148de5b621..0000000000
--- a/sound/decoders/iff_sound.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sound/decoders/iff_sound.h"
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/raw.h"
-#include "common/iff_container.h"
-#include "common/func.h"
-
-namespace Audio {
-
-struct Voice8Header {
- uint32 oneShotHiSamples;
- uint32 repeatHiSamples;
- uint32 samplesPerHiCycle;
- uint16 samplesPerSec;
- byte octaves;
- byte compression;
- uint32 volume;
-
- Voice8Header() {
- memset(this, 0, sizeof(Voice8Header));
- }
-
- void load(Common::ReadStream &stream);
-};
-
-void Voice8Header::load(Common::ReadStream &stream) {
- oneShotHiSamples = stream.readUint32BE();
- repeatHiSamples = stream.readUint32BE();
- samplesPerHiCycle = stream.readUint32BE();
- samplesPerSec = stream.readUint16BE();
- octaves = stream.readByte();
- compression = stream.readByte();
- volume = stream.readUint32BE();
-}
-
-
-
-struct A8SVXLoader {
- Voice8Header _header;
- int8 *_data;
- uint32 _dataSize;
-
- void load(Common::ReadStream &input) {
- Common::IFFParser parser(&input);
- Common::Functor1Mem< Common::IFFChunk&, bool, A8SVXLoader > c(this, &A8SVXLoader::callback);
- parser.parse(c);
- }
-
- bool callback(Common::IFFChunk &chunk) {
- switch (chunk._type) {
- case ID_VHDR:
- _header.load(*chunk._stream);
- break;
-
- case ID_BODY:
- _dataSize = chunk._size;
- _data = (int8*)malloc(_dataSize);
- assert(_data);
- loadData(chunk._stream);
- return true;
- }
-
- return false;
- }
-
- void loadData(Common::ReadStream *stream) {
- switch (_header.compression) {
- case 0:
- stream->read(_data, _dataSize);
- break;
-
- case 1:
- // implement other formats here
- error("compressed IFF audio is not supported");
- break;
- }
-
- }
-};
-
-
-AudioStream *make8SVXStream(Common::ReadStream &input, bool loop) {
- A8SVXLoader loader;
- loader.load(input);
-
- SeekableAudioStream *stream = Audio::makeRawStream((byte *)loader._data, loader._dataSize, loader._header.samplesPerSec, 0);
-
- uint32 loopStart = 0, loopEnd = 0;
- if (loop) {
- // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
- // repeatHiSamples fields
- loopStart = 0;
- loopEnd = loader._header.oneShotHiSamples + loader._header.repeatHiSamples;
-
- if (loopStart != loopEnd) {
- return new SubLoopingAudioStream(stream, 0,
- Timestamp(0, loopStart, loader._header.samplesPerSec),
- Timestamp(0, loopEnd, loader._header.samplesPerSec));
- }
- }
-
- return stream;
-}
-
-}
diff --git a/sound/decoders/iff_sound.h b/sound/decoders/iff_sound.h
deleted file mode 100644
index 4e53059380..0000000000
--- a/sound/decoders/iff_sound.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - parallaction
- */
-
-#ifndef SOUND_IFF_H
-#define SOUND_IFF_H
-
-namespace Common {
- class ReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-
-AudioStream *make8SVXStream(Common::ReadStream &stream, bool loop);
-
-}
-
-#endif
diff --git a/sound/decoders/mac_snd.cpp b/sound/decoders/mac_snd.cpp
deleted file mode 100644
index 48f6886bf4..0000000000
--- a/sound/decoders/mac_snd.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/*
- * The code in this file is based on information found at
- * http://developer.apple.com/legacy/mac/library/documentation/mac/Sound/Sound-60.html#HEADING60-15
- *
- * We implement both type 1 and type 2 snd resources, but only those that are sampled
- */
-
-#include "common/util.h"
-#include "common/stream.h"
-
-#include "sound/decoders/mac_snd.h"
-#include "sound/audiostream.h"
-#include "sound/decoders/raw.h"
-
-namespace Audio {
-
-SeekableAudioStream *makeMacSndStream(Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse) {
-
- uint16 sndType = stream->readUint16BE();
-
- if (sndType == 1) {
- // "normal" snd resources
- if (stream->readUint16BE() != 1) {
- warning("makeMacSndStream(): Unsupported data type count");
- return 0;
- }
-
- if (stream->readUint16BE() != 5) {
- // 5 == sampled
- warning("makeMacSndStream(): Unsupported data type");
- return 0;
- }
-
- stream->readUint32BE(); // initialization option
- } else if (sndType == 2) {
- // old HyperCard snd resources
- stream->readUint16BE(); // reference count (unused)
- } else {
- warning("makeMacSndStream(): Unknown format type %d", sndType);
- return 0;
- }
-
- // We really should never get this as long as we have sampled data only
- if (stream->readUint16BE() != 1) {
- warning("makeMacSndStream(): Unsupported command count");
- return 0;
- }
-
- uint16 command = stream->readUint16BE();
-
- // 0x8050 - soundCmd (with dataOffsetFlag set): install a sampled sound as a voice
- // 0x8051 - bufferCmd (with dataOffsetFlag set): play a sample sound
- if (command != 0x8050 && command != 0x8051) {
- warning("makeMacSndStream(): Unsupported command %04x", command);
- return 0;
- }
-
- stream->readUint16BE(); // 0
- uint32 soundHeaderOffset = stream->readUint32BE();
-
- stream->seek(soundHeaderOffset);
-
- uint32 soundDataOffset = stream->readUint32BE();
- uint32 size = stream->readUint32BE();
- uint16 rate = stream->readUint32BE() >> 16; // Really fixed point, but we only support integer rates
- stream->readUint32BE(); // loop start
- stream->readUint32BE(); // loop end
- byte encoding = stream->readByte();
- stream->readByte(); // base frequency
-
- if (encoding != 0) {
- // 0 == PCM
- warning("makeMacSndStream(): Unsupported compression %d", encoding);
- return 0;
- }
-
- stream->skip(soundDataOffset);
-
- byte *data = (byte *)malloc(size);
- assert(data);
- stream->read(data, size);
-
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
-
- // Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES.
- return makeRawStream(data, size, rate, Audio::FLAG_UNSIGNED);
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/mac_snd.h b/sound/decoders/mac_snd.h
deleted file mode 100644
index 198a61333e..0000000000
--- a/sound/decoders/mac_snd.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - sci
- */
-
-#ifndef SOUND_MAC_SND_H
-#define SOUND_MAC_SND_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-namespace Common { class SeekableReadStream; }
-
-namespace Audio {
-
-class SeekableAudioStream;
-
-/**
- * Try to load a Mac snd resource from the given seekable stream and create a SeekableAudioStream
- * from that data.
- *
- * @param stream the SeekableReadStream from which to read the snd data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occurred
- */
-SeekableAudioStream *makeMacSndStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif
diff --git a/sound/decoders/mp3.cpp b/sound/decoders/mp3.cpp
deleted file mode 100644
index e06b82a9e2..0000000000
--- a/sound/decoders/mp3.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sound/decoders/mp3.h"
-
-#ifdef USE_MAD
-
-#include "common/debug.h"
-#include "common/stream.h"
-#include "common/util.h"
-
-#include "sound/audiostream.h"
-
-#include <mad.h>
-
-#if defined(__PSP__)
- #include "backends/platform/psp/mp3.h"
-#endif
-namespace Audio {
-
-
-#pragma mark -
-#pragma mark --- MP3 (MAD) stream ---
-#pragma mark -
-
-
-class MP3Stream : public SeekableAudioStream {
-protected:
- enum State {
- MP3_STATE_INIT, // Need to init the decoder
- MP3_STATE_READY, // ready for processing data
- MP3_STATE_EOS // end of data reached (may need to loop)
- };
-
- Common::SeekableReadStream *_inStream;
- DisposeAfterUse::Flag _disposeAfterUse;
-
- uint _posInFrame;
- State _state;
-
- Timestamp _length;
- mad_timer_t _totalTime;
-
- mad_stream _stream;
- mad_frame _frame;
- mad_synth _synth;
-
- enum {
- BUFFER_SIZE = 5 * 8192
- };
-
- // This buffer contains a slab of input data
- byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
-
-public:
- MP3Stream(Common::SeekableReadStream *inStream,
- DisposeAfterUse::Flag dispose);
- ~MP3Stream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return _state == MP3_STATE_EOS; }
- bool isStereo() const { return MAD_NCHANNELS(&_frame.header) == 2; }
- int getRate() const { return _frame.header.samplerate; }
-
- bool seek(const Timestamp &where);
- Timestamp getLength() const { return _length; }
-protected:
- void decodeMP3Data();
- void readMP3Data();
-
- void initStream();
- void readHeader();
- void deinitStream();
-};
-
-MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
- _inStream(inStream),
- _disposeAfterUse(dispose),
- _posInFrame(0),
- _state(MP3_STATE_INIT),
- _length(0, 1000),
- _totalTime(mad_timer_zero) {
-
- // The MAD_BUFFER_GUARD must always contain zeros (the reason
- // for this is that the Layer III Huffman decoder of libMAD
- // may read a few bytes beyond the end of the input buffer).
- memset(_buf + BUFFER_SIZE, 0, MAD_BUFFER_GUARD);
-
- // Calculate the length of the stream
- initStream();
-
- while (_state != MP3_STATE_EOS)
- readHeader();
-
- // To rule out any invalid sample rate to be encountered here, say in case the
- // MP3 stream is invalid, we just check the MAD error code here.
- // We need to assure this, since else we might trigger an assertion in Timestamp
- // (When getRate() returns 0 or a negative number to be precise).
- // Note that we allow "MAD_ERROR_BUFLEN" as error code here, since according
- // to mad.h it is also set on EOF.
- if ((_stream.error == MAD_ERROR_NONE || _stream.error == MAD_ERROR_BUFLEN) && getRate() > 0)
- _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
-
- deinitStream();
-
- // Reinit stream
- _state = MP3_STATE_INIT;
-
- // Decode the first chunk of data. This is necessary so that _frame
- // is setup and isStereo() and getRate() return correct results.
- decodeMP3Data();
-}
-
-MP3Stream::~MP3Stream() {
- deinitStream();
-
- if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _inStream;
-}
-
-void MP3Stream::decodeMP3Data() {
- do {
- if (_state == MP3_STATE_INIT)
- initStream();
-
- if (_state == MP3_STATE_EOS)
- return;
-
- // If necessary, load more data into the stream decoder
- if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data();
-
- while (_state == MP3_STATE_READY) {
- _stream.error = MAD_ERROR_NONE;
-
- // Decode the next frame
- if (mad_frame_decode(&_frame, &_stream) == -1) {
- if (_stream.error == MAD_ERROR_BUFLEN) {
- break; // Read more data
- } else if (MAD_RECOVERABLE(_stream.error)) {
- // Note: we will occasionally see MAD_ERROR_BADDATAPTR errors here.
- // These are normal and expected (caused by our frame skipping (i.e. "seeking")
- // code above).
- debug(6, "MP3Stream: Recoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
- continue;
- } else {
- warning("MP3Stream: Unrecoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
- break;
- }
- }
-
- // Synthesize PCM data
- mad_synth_frame(&_synth, &_frame);
- _posInFrame = 0;
- break;
- }
- } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
-
- if (_stream.error != MAD_ERROR_NONE)
- _state = MP3_STATE_EOS;
-}
-
-void MP3Stream::readMP3Data() {
- uint32 remaining = 0;
-
- // Give up immediately if we already used up all data in the stream
- if (_inStream->eos()) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- if (_stream.next_frame) {
- // If there is still data in the MAD stream, we need to preserve it.
- // Note that we use memmove, as we are reusing the same buffer,
- // and hence the data regions we copy from and to may overlap.
- remaining = _stream.bufend - _stream.next_frame;
- assert(remaining < BUFFER_SIZE); // Paranoia check
- memmove(_buf, _stream.next_frame, remaining);
- }
-
- // Try to read the next block
- uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
- if (size <= 0) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- // Feed the data we just read into the stream decoder
- _stream.error = MAD_ERROR_NONE;
- mad_stream_buffer(&_stream, _buf, size + remaining);
-}
-
-bool MP3Stream::seek(const Timestamp &where) {
- if (where == _length) {
- _state = MP3_STATE_EOS;
- return true;
- } else if (where > _length) {
- return false;
- }
-
- const uint32 time = where.msecs();
-
- mad_timer_t destination;
- mad_timer_set(&destination, time / 1000, time % 1000, 1000);
-
- if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0)
- initStream();
-
- while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
- readHeader();
-
- decodeMP3Data();
-
- return (_state != MP3_STATE_EOS);
-}
-
-void MP3Stream::initStream() {
- if (_state != MP3_STATE_INIT)
- deinitStream();
-
- // Init MAD
- mad_stream_init(&_stream);
- mad_frame_init(&_frame);
- mad_synth_init(&_synth);
-
- // Reset the stream data
- _inStream->seek(0, SEEK_SET);
- _totalTime = mad_timer_zero;
- _posInFrame = 0;
-
- // Update state
- _state = MP3_STATE_READY;
-
- // Read the first few sample bytes
- readMP3Data();
-}
-
-void MP3Stream::readHeader() {
- if (_state != MP3_STATE_READY)
- return;
-
- // If necessary, load more data into the stream decoder
- if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data();
-
- while (_state != MP3_STATE_EOS) {
- _stream.error = MAD_ERROR_NONE;
-
- // Decode the next header. Note: mad_frame_decode would do this for us, too.
- // However, for seeking we don't want to decode the full frame (else it would
- // be far too slow). Hence we perform this explicitly in a separate step.
- if (mad_header_decode(&_frame.header, &_stream) == -1) {
- if (_stream.error == MAD_ERROR_BUFLEN) {
- readMP3Data(); // Read more data
- continue;
- } else if (MAD_RECOVERABLE(_stream.error)) {
- debug(6, "MP3Stream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- continue;
- } else {
- warning("MP3Stream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- break;
- }
- }
-
- // Sum up the total playback time so far
- mad_timer_add(&_totalTime, _frame.header.duration);
- break;
- }
-
- if (_stream.error != MAD_ERROR_NONE)
- _state = MP3_STATE_EOS;
-}
-
-void MP3Stream::deinitStream() {
- if (_state == MP3_STATE_INIT)
- return;
-
- // Deinit MAD
- mad_synth_finish(&_synth);
- mad_frame_finish(&_frame);
- mad_stream_finish(&_stream);
-
- _state = MP3_STATE_EOS;
-}
-
-static inline int scale_sample(mad_fixed_t sample) {
- // round
- sample += (1L << (MAD_F_FRACBITS - 16));
-
- // clip
- if (sample > MAD_F_ONE - 1)
- sample = MAD_F_ONE - 1;
- else if (sample < -MAD_F_ONE)
- sample = -MAD_F_ONE;
-
- // quantize and scale to not saturate when mixing a lot of channels
- return sample >> (MAD_F_FRACBITS + 1 - 16);
-}
-
-int MP3Stream::readBuffer(int16 *buffer, const int numSamples) {
- int samples = 0;
- // Keep going as long as we have input available
- while (samples < numSamples && _state != MP3_STATE_EOS) {
- const int len = MIN(numSamples, samples + (int)(_synth.pcm.length - _posInFrame) * MAD_NCHANNELS(&_frame.header));
- while (samples < len) {
- *buffer++ = (int16)scale_sample(_synth.pcm.samples[0][_posInFrame]);
- samples++;
- if (MAD_NCHANNELS(&_frame.header) == 2) {
- *buffer++ = (int16)scale_sample(_synth.pcm.samples[1][_posInFrame]);
- samples++;
- }
- _posInFrame++;
- }
- if (_posInFrame >= _synth.pcm.length) {
- // We used up all PCM data in the current frame -- read & decode more
- decodeMP3Data();
- }
- }
- return samples;
-}
-
-
-#pragma mark -
-#pragma mark --- MP3 factory functions ---
-#pragma mark -
-
-SeekableAudioStream *makeMP3Stream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse) {
-
-#if defined(__PSP__)
- SeekableAudioStream *s = 0;
-
- if (Mp3PspStream::isOkToCreateStream())
- s = new Mp3PspStream(stream, disposeAfterUse);
-
- if (!s) // go to regular MAD mp3 stream if ME fails
- s = new MP3Stream(stream, disposeAfterUse);
-#else
- SeekableAudioStream *s = new MP3Stream(stream, disposeAfterUse);
-#endif
- if (s && s->endOfData()) {
- delete s;
- return 0;
- } else {
- return s;
- }
-}
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_MAD
diff --git a/sound/decoders/mp3.h b/sound/decoders/mp3.h
deleted file mode 100644
index 72bc6e1b3e..0000000000
--- a/sound/decoders/mp3.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - draci
- * - kyra
- * - m4
- * - mohawk
- * - queen
- * - saga
- * - sci
- * - scumm
- * - sword1
- * - sword2
- * - touche
- * - tucker
- */
-
-#ifndef SOUND_MP3_H
-#define SOUND_MP3_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-#ifdef USE_MAD
-
-namespace Common {
- class SeekableReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-/**
- * Create a new SeekableAudioStream from the MP3 data in the given stream.
- * Allows for seeking (which is why we require a SeekableReadStream).
- *
- * @param stream the SeekableReadStream from which to read the MP3 data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occurred
- */
-SeekableAudioStream *makeMP3Stream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_MAD
-#endif // #ifndef SOUND_MP3_H
diff --git a/sound/decoders/raw.cpp b/sound/decoders/raw.cpp
deleted file mode 100644
index aedddbf6c4..0000000000
--- a/sound/decoders/raw.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/endian.h"
-#include "common/memstream.h"
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/raw.h"
-
-namespace Audio {
-
-// This used to be an inline template function, but
-// buggy template function handling in MSVC6 forced
-// us to go with the macro approach. So far this is
-// the only template function that MSVC6 seemed to
-// compile incorrectly. Knock on wood.
-#define READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, ptr, isLE) \
- ((is16Bit ? (isLE ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr)) : (*ptr << 8)) ^ (isUnsigned ? 0x8000 : 0))
-
-
-#pragma mark -
-#pragma mark --- RawStream ---
-#pragma mark -
-
-/**
- * This is a stream, which allows for playing raw PCM data from a stream.
- * It also features playback of multiple blocks from a given stream.
- */
-template<bool is16Bit, bool isUnsigned, bool isLE>
-class RawStream : public SeekableAudioStream {
-public:
- RawStream(int rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream, const RawStreamBlockList &blocks)
- : _rate(rate), _isStereo(stereo), _playtime(0, rate), _stream(stream), _disposeAfterUse(disposeStream), _blocks(blocks), _curBlock(_blocks.begin()), _blockLeft(0), _buffer(0) {
-
- assert(_blocks.size() > 0);
-
- // Setup our buffer for readBuffer
- _buffer = new byte[kSampleBufferLength * (is16Bit ? 2 : 1)];
- assert(_buffer);
-
- // Set current buffer state, playing first block
- _stream->seek(_curBlock->pos, SEEK_SET);
-
- // In case of an error we will stop (or rather
- // not start) stream playback.
- if (_stream->err()) {
- _blockLeft = 0;
- _curBlock = _blocks.end();
- } else {
- _blockLeft = _curBlock->len;
- }
-
- // Add up length of all blocks in order to caluclate total play time
- int32 len = 0;
- for (RawStreamBlockList::const_iterator i = _blocks.begin(); i != _blocks.end(); ++i) {
- assert(i->len % (_isStereo ? 2 : 1) == 0);
- len += i->len;
- }
-
- _playtime = Timestamp(0, len / (_isStereo ? 2 : 1), rate);
- }
-
- ~RawStream() {
- if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _stream;
-
- delete[] _buffer;
- }
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool isStereo() const { return _isStereo; }
- bool endOfData() const { return (_curBlock == _blocks.end()) && (_blockLeft == 0); }
-
- int getRate() const { return _rate; }
- Timestamp getLength() const { return _playtime; }
-
- bool seek(const Timestamp &where);
-private:
- const int _rate; ///< Sample rate of stream
- const bool _isStereo; ///< Whether this is an stereo stream
- Timestamp _playtime; ///< Calculated total play time
- Common::SeekableReadStream *_stream; ///< Stream to read data from
- const DisposeAfterUse::Flag _disposeAfterUse; ///< Indicates whether the stream object should be deleted when this RawStream is destructed
- const RawStreamBlockList _blocks; ///< Audio block list
-
- RawStreamBlockList::const_iterator _curBlock; ///< Current audio block number
- int32 _blockLeft; ///< How many bytes are still left in the current block
-
- /**
- * Advance one block in the stream in case
- * the current one is empty.
- */
- void updateBlockIfNeeded();
-
- byte *_buffer; ///< Buffer used in readBuffer
- enum {
- /**
- * How many samples we can buffer at once.
- *
- * TODO: Check whether this size suffices
- * for systems with slow disk I/O.
- */
- kSampleBufferLength = 2048
- };
-
- /**
- * Fill the temporary sample buffer used in readBuffer.
- *
- * @param maxSamples Maximum samples to read.
- * @return actual count of samples read.
- */
- int fillBuffer(int maxSamples);
-};
-
-template<bool is16Bit, bool isUnsigned, bool isLE>
-int RawStream<is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
- int samplesLeft = numSamples;
-
- while (samplesLeft > 0) {
- // Try to read up to "samplesLeft" samples.
- int len = fillBuffer(samplesLeft);
-
- // In case we were not able to read any samples
- // we will stop reading here.
- if (!len)
- break;
-
- // Adjust the samples left to read.
- samplesLeft -= len;
-
- // Copy the data to the caller's buffer.
- const byte *src = _buffer;
- while (len-- > 0) {
- *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, src, isLE);
- src += (is16Bit ? 2 : 1);
- }
- }
-
- return numSamples - samplesLeft;
-}
-
-template<bool is16Bit, bool isUnsigned, bool isLE>
-int RawStream<is16Bit, isUnsigned, isLE>::fillBuffer(int maxSamples) {
- int bufferedSamples = 0;
- byte *dst = _buffer;
-
- // We can only read up to "kSampleBufferLength" samples
- // so we take this into consideration, when trying to
- // read up to maxSamples.
- maxSamples = MIN<int>(kSampleBufferLength, maxSamples);
-
- // We will only read up to maxSamples
- while (maxSamples > 0 && !endOfData()) {
- // Calculate how many samples we can safely read
- // from the current block.
- const int len = MIN<int>(maxSamples, _blockLeft);
-
- // Try to read all the sample data and update the
- // destination pointer.
- const int bytesRead = _stream->read(dst, len * (is16Bit ? 2 : 1));
- dst += bytesRead;
-
- // Calculate how many samples we actually read.
- const int samplesRead = bytesRead / (is16Bit ? 2 : 1);
-
- // Update all status variables
- bufferedSamples += samplesRead;
- maxSamples -= samplesRead;
- _blockLeft -= samplesRead;
-
- // In case of an error we will stop
- // stream playback.
- if (_stream->err()) {
- _blockLeft = 0;
- _curBlock = _blocks.end();
- }
-
- // Advance to the next block in case the current
- // one is already finished.
- updateBlockIfNeeded();
- }
-
- return bufferedSamples;
-}
-
-template<bool is16Bit, bool isUnsigned, bool isLE>
-void RawStream<is16Bit, isUnsigned, isLE>::updateBlockIfNeeded() {
- // Have we now finished this block? If so, read the next block
- if (_blockLeft == 0 && _curBlock != _blocks.end()) {
- // Next block
- ++_curBlock;
-
- // Check whether we reached the end of the stream
- // yet. In case we did not do this, we will just
- // setup the next block as new block.
- if (_curBlock != _blocks.end()) {
- _stream->seek(_curBlock->pos, SEEK_SET);
-
- // In case of an error we will stop
- // stream playback.
- if (_stream->err()) {
- _blockLeft = 0;
- _curBlock = _blocks.end();
- } else {
- _blockLeft = _curBlock->len;
- }
- }
- }
-}
-
-template<bool is16Bit, bool isUnsigned, bool isLE>
-bool RawStream<is16Bit, isUnsigned, isLE>::seek(const Timestamp &where) {
- _blockLeft = 0;
- _curBlock = _blocks.end();
-
- if (where > _playtime)
- return false;
-
- const uint32 seekSample = convertTimeToStreamPos(where, getRate(), isStereo()).totalNumberOfFrames();
- uint32 curSample = 0;
-
- // Search for the disk block in which the specific sample is placed
- for (_curBlock = _blocks.begin(); _curBlock != _blocks.end(); ++_curBlock) {
- uint32 nextBlockSample = curSample + _curBlock->len;
-
- if (nextBlockSample > seekSample)
- break;
-
- curSample = nextBlockSample;
- }
-
- if (_curBlock == _blocks.end()) {
- return ((seekSample - curSample) == 0);
- } else {
- const uint32 offset = seekSample - curSample;
-
- _stream->seek(_curBlock->pos + offset * (is16Bit ? 2 : 1), SEEK_SET);
-
- // In case of an error we will stop
- // stream playback.
- if (_stream->err()) {
- _blockLeft = 0;
- _curBlock = _blocks.end();
- } else {
- _blockLeft = _curBlock->len - offset;
- }
-
- return true;
- }
-}
-
-#pragma mark -
-#pragma mark --- Raw stream factories ---
-#pragma mark -
-
-/* In the following, we use preprocessor / macro tricks to simplify the code
- * which instantiates the input streams. We used to use template functions for
- * this, but MSVC6 / EVC 3-4 (used for WinCE builds) are extremely buggy when it
- * comes to this feature of C++... so as a compromise we use macros to cut down
- * on the (source) code duplication a bit.
- * So while normally macro tricks are said to make maintenance harder, in this
- * particular case it should actually help it :-)
- */
-
-#define MAKE_RAW_STREAM(UNSIGNED) \
- if (is16Bit) { \
- if (isLE) \
- return new RawStream<true, UNSIGNED, true>(rate, isStereo, disposeAfterUse, stream, blockList); \
- else \
- return new RawStream<true, UNSIGNED, false>(rate, isStereo, disposeAfterUse, stream, blockList); \
- } else \
- return new RawStream<false, UNSIGNED, false>(rate, isStereo, disposeAfterUse, stream, blockList)
-
-SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
- const RawStreamBlockList &blockList,
- int rate,
- byte flags,
- DisposeAfterUse::Flag disposeAfterUse) {
- const bool isStereo = (flags & Audio::FLAG_STEREO) != 0;
- const bool is16Bit = (flags & Audio::FLAG_16BITS) != 0;
- const bool isUnsigned = (flags & Audio::FLAG_UNSIGNED) != 0;
- const bool isLE = (flags & Audio::FLAG_LITTLE_ENDIAN) != 0;
-
- if (blockList.empty()) {
- warning("Empty block list passed to makeRawStream");
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
- return 0;
- }
-
- if (isUnsigned) {
- MAKE_RAW_STREAM(true);
- } else {
- MAKE_RAW_STREAM(false);
- }
-}
-
-SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
- int rate, byte flags,
- DisposeAfterUse::Flag disposeAfterUse) {
- RawStreamBlockList blocks;
- RawStreamBlock block;
- block.pos = 0;
-
- const bool isStereo = (flags & Audio::FLAG_STEREO) != 0;
- const bool is16Bit = (flags & Audio::FLAG_16BITS) != 0;
-
- assert(stream->size() % ((is16Bit ? 2 : 1) * (isStereo ? 2 : 1)) == 0);
-
- block.len = stream->size() / (is16Bit ? 2 : 1);
- blocks.push_back(block);
-
- return makeRawStream(stream, blocks, rate, flags, disposeAfterUse);
-}
-
-SeekableAudioStream *makeRawStream(const byte *buffer, uint32 size,
- int rate, byte flags,
- DisposeAfterUse::Flag disposeAfterUse) {
- return makeRawStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, flags, DisposeAfterUse::YES);
-}
-
-SeekableAudioStream *makeRawDiskStream_OLD(Common::SeekableReadStream *stream, RawStreamBlock *block, int numBlocks,
- int rate, byte flags, DisposeAfterUse::Flag disposeStream) {
- assert(numBlocks > 0);
- RawStreamBlockList blocks;
- for (int i = 0; i < numBlocks; ++i)
- blocks.push_back(block[i]);
-
- return makeRawStream(stream, blocks, rate, flags, disposeStream);
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/raw.h b/sound/decoders/raw.h
deleted file mode 100644
index 3e9426012c..0000000000
--- a/sound/decoders/raw.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef SOUND_RAW_H
-#define SOUND_RAW_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-#include "common/list.h"
-
-
-namespace Common { class SeekableReadStream; }
-
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-/**
- * Various flags which can be bit-ORed and then passed to
- * makeRawStream and some other AudioStream factories
- * to control their behavior.
- *
- * Engine authors are advised not to rely on a certain value or
- * order of these flags (in particular, do not store them verbatim
- * in savestates).
- */
-enum RawFlags {
- /** unsigned samples (default: signed) */
- FLAG_UNSIGNED = 1 << 0,
-
- /** sound is 16 bits wide (default: 8bit) */
- FLAG_16BITS = 1 << 1,
-
- /** samples are little endian (default: big endian) */
- FLAG_LITTLE_ENDIAN = 1 << 2,
-
- /** sound is in stereo (default: mono) */
- FLAG_STEREO = 1 << 3
-};
-
-
-/**
- * Struct used to define the audio data to be played by a RawStream.
- */
-struct RawStreamBlock {
- int32 pos; ///< Position in stream of the block (in bytes of course!)
- int32 len; ///< Length of the block (in raw samples, not sample pairs!)
-};
-
-/**
- * List containing all blocks of a raw stream.
- * @see RawStreamBlock
- */
-typedef Common::List<RawStreamBlock> RawStreamBlockList;
-
-/**
- * Creates an audio stream, which plays from the given buffer.
- *
- * @param buffer Buffer to play from.
- * @param size Size of the buffer in bytes.
- * @param rate Rate of the sound data.
- * @param flags Audio flags combination.
- * @see RawFlags
- * @param disposeAfterUse Whether to free the buffer after use (with free!).
- * @return The new SeekableAudioStream (or 0 on failure).
- */
-SeekableAudioStream *makeRawStream(const byte *buffer, uint32 size,
- int rate, byte flags,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
-
-/**
- * Creates an audio stream, which plays from the given stream.
- *
- * @param stream Stream object to play from.
- * @param rate Rate of the sound data.
- * @param flags Audio flags combination.
- * @see RawFlags
- * @param disposeAfterUse Whether to delete the stream after use.
- * @return The new SeekableAudioStream (or 0 on failure).
- */
-SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
- int rate, byte flags,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
-
-/**
- * Creates an audio stream, which plays from the given stream.
- *
- * @param stream Stream object to play from.
- * @param blockList List of blocks to play.
- * @see RawDiskStreamAudioBlock
- * @see RawStreamBlockList
- * @param rate Rate of the sound data.
- * @param flags Audio flags combination.
- * @see RawFlags
- * @param disposeAfterUse Whether to delete the stream after use.
- * @return The new SeekableAudioStream (or 0 on failure).
- */
-SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
- const RawStreamBlockList &blockList,
- int rate,
- byte flags,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
-
-/**
- * NOTE:
- * This API is considered deprecated.
- *
- * Creates a audio stream, which plays from given stream.
- *
- * @param stream Stream to play from
- * @param block Pointer to an RawStreamBlock array
- * @see RawStreamBlock
- * @param numBlocks Number of blocks.
- * @param rate The rate
- * @param flags Flags combination.
- * @see RawFlags
- * @param disposeStream Whether the "stream" object should be destroyed after playback.
- * @return The new SeekableAudioStream (or 0 on failure).
- */
-SeekableAudioStream *makeRawDiskStream_OLD(Common::SeekableReadStream *stream,
- RawStreamBlock *block, int numBlocks,
- int rate, byte flags,
- DisposeAfterUse::Flag disposeStream);
-
-
-} // End of namespace Audio
-
-#endif
diff --git a/sound/decoders/vag.cpp b/sound/decoders/vag.cpp
deleted file mode 100644
index d3f0811f2b..0000000000
--- a/sound/decoders/vag.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sound/decoders/vag.h"
-#include "sound/audiostream.h"
-#include "common/stream.h"
-
-namespace Audio {
-
-class VagStream : public Audio::RewindableAudioStream {
-public:
- VagStream(Common::SeekableReadStream *stream, int rate);
- ~VagStream();
-
- bool isStereo() const { return false; }
- bool endOfData() const { return _stream->pos() == _stream->size(); }
- int getRate() const { return _rate; }
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool rewind();
-private:
- Common::SeekableReadStream *_stream;
-
- byte _predictor;
- double _samples[28];
- byte _samplesRemaining;
- int _rate;
- double _s1, _s2;
-};
-
-VagStream::VagStream(Common::SeekableReadStream *stream, int rate) : _stream(stream) {
- _samplesRemaining = 0;
- _predictor = 0;
- _s1 = _s2 = 0.0;
- _rate = rate;
-}
-
-
-VagStream::~VagStream() {
- delete _stream;
-}
-
-static const double s_vagDataTable[5][2] =
- {
- { 0.0, 0.0 },
- { 60.0 / 64.0, 0.0 },
- { 115.0 / 64.0, -52.0 / 64.0 },
- { 98.0 / 64.0, -55.0 / 64.0 },
- { 122.0 / 64.0, -60.0 / 64.0 }
- };
-
-int VagStream::readBuffer(int16 *buffer, const int numSamples) {
- int32 samplesDecoded = 0;
-
- if (_samplesRemaining) {
- byte i = 0;
-
- for (i = 28 - _samplesRemaining; i < 28 && samplesDecoded < numSamples; i++) {
- _samples[i] = _samples[i] + _s1 * s_vagDataTable[_predictor][0] + _s2 * s_vagDataTable[_predictor][1];
- _s2 = _s1;
- _s1 = _samples[i];
- int16 d = (int) (_samples[i] + 0.5);
- buffer[samplesDecoded] = d;
- samplesDecoded++;
- }
-
-#if 0
- assert(i == 28); // We're screwed if this fails :P
-#endif
- // This might mean the file is corrupted, or that the stream has
- // been closed.
- if (i != 28) return 0;
-
- _samplesRemaining = 0;
- }
-
- while (samplesDecoded < numSamples) {
- byte i = 0;
-
- _predictor = _stream->readByte();
- byte shift = _predictor & 0xf;
- _predictor >>= 4;
-
- if (_stream->readByte() == 7)
- return samplesDecoded;
-
- for (i = 0; i < 28; i += 2) {
- byte d = _stream->readByte();
- int16 s = (d & 0xf) << 12;
- if (s & 0x8000)
- s |= 0xffff0000;
- _samples[i] = (double)(s >> shift);
- s = (d & 0xf0) << 8;
- if (s & 0x8000)
- s |= 0xffff0000;
- _samples[i + 1] = (double)(s >> shift);
- }
-
- for (i = 0; i < 28 && samplesDecoded < numSamples; i++) {
- _samples[i] = _samples[i] + _s1 * s_vagDataTable[_predictor][0] + _s2 * s_vagDataTable[_predictor][1];
- _s2 = _s1;
- _s1 = _samples[i];
- int16 d = (int) (_samples[i] + 0.5);
- buffer[samplesDecoded] = d;
- samplesDecoded++;
- }
-
- if (i != 27)
- _samplesRemaining = 28 - i;
- }
-
- return samplesDecoded;
-}
-
-bool VagStream::rewind() {
- _stream->seek(0);
- _samplesRemaining = 0;
- _predictor = 0;
- _s1 = _s2 = 0.0;
-
- return true;
-}
-
-RewindableAudioStream *makeVagStream(Common::SeekableReadStream *stream, int rate) {
- return new VagStream(stream, rate);
-}
-
-}
diff --git a/sound/decoders/vag.h b/sound/decoders/vag.h
deleted file mode 100644
index cdf91a8ea1..0000000000
--- a/sound/decoders/vag.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - sword1 (PSX port of the game)
- * - sword2 (PSX port of the game)
- * - tinsel (PSX port of the game)
- */
-
-#ifndef SOUND_VAG_H
-#define SOUND_VAG_H
-
-namespace Common {
- class SeekableReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-class RewindableAudioStream;
-
-/**
- * Takes an input stream containing Vag sound data and creates
- * an RewindableAudioStream from that.
- *
- * @param stream the SeekableReadStream from which to read the ADPCM data
- * @param rate the sampling rate
- * @return a new RewindableAudioStream, or NULL, if an error occurred
- */
-RewindableAudioStream *makeVagStream(
- Common::SeekableReadStream *stream,
- int rate = 11025);
-
-} // End of namespace Sword1
-
-#endif
diff --git a/sound/decoders/voc.cpp b/sound/decoders/voc.cpp
deleted file mode 100644
index e9af7ece3f..0000000000
--- a/sound/decoders/voc.cpp
+++ /dev/null
@@ -1,403 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/debug.h"
-#include "common/endian.h"
-#include "common/util.h"
-#include "common/stream.h"
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/raw.h"
-#include "sound/decoders/voc.h"
-
-
-namespace Audio {
-
-int getSampleRateFromVOCRate(int vocSR) {
- if (vocSR == 0xa5 || vocSR == 0xa6) {
- return 11025;
- } else if (vocSR == 0xd2 || vocSR == 0xd3) {
- return 22050;
- } else {
- int sr = 1000000L / (256L - vocSR);
- // inexact sampling rates occur e.g. in the kitchen in Monkey Island,
- // very easy to reach right from the start of the game.
- //warning("inexact sample rate used: %i (0x%x)", sr, vocSR);
- return sr;
- }
-}
-
-static byte *loadVOCFromStream(Common::ReadStream &stream, int &size, int &rate, int &loops, int &begin_loop, int &end_loop) {
- VocFileHeader fileHeader;
-
- debug(2, "loadVOCFromStream");
-
- if (stream.read(&fileHeader, 8) != 8)
- goto invalid;
-
- if (!memcmp(&fileHeader, "VTLK", 4)) {
- if (stream.read(&fileHeader, sizeof(VocFileHeader)) != sizeof(VocFileHeader))
- goto invalid;
- } else if (!memcmp(&fileHeader, "Creative", 8)) {
- if (stream.read(((byte *)&fileHeader) + 8, sizeof(VocFileHeader) - 8) != sizeof(VocFileHeader) - 8)
- goto invalid;
- } else {
- invalid:;
- warning("loadVOCFromStream: Invalid header");
- return NULL;
- }
-
- if (memcmp(fileHeader.desc, "Creative Voice File", 19) != 0)
- error("loadVOCFromStream: Invalid header");
- if (fileHeader.desc[19] != 0x1A)
- debug(3, "loadVOCFromStream: Partially invalid header");
-
- int32 offset = FROM_LE_16(fileHeader.datablock_offset);
- int16 version = FROM_LE_16(fileHeader.version);
- int16 code = FROM_LE_16(fileHeader.id);
- assert(offset == sizeof(VocFileHeader));
- // 0x100 is an invalid VOC version used by German version of DOTT (Disk) and
- // French version of Simon the Sorcerer 2 (CD)
- assert(version == 0x010A || version == 0x0114 || version == 0x0100);
- assert(code == ~version + 0x1234);
-
- int len;
- byte *ret_sound = 0;
- size = 0;
- begin_loop = 0;
- end_loop = 0;
-
- while ((code = stream.readByte())) {
- len = stream.readByte();
- len |= stream.readByte() << 8;
- len |= stream.readByte() << 16;
-
- debug(2, "Block code %d, len %d", code, len);
-
- switch (code) {
- case 1:
- case 9: {
- int packing;
- if (code == 1) {
- int time_constant = stream.readByte();
- packing = stream.readByte();
- len -= 2;
- rate = getSampleRateFromVOCRate(time_constant);
- } else {
- rate = stream.readUint32LE();
- int bits = stream.readByte();
- int channels = stream.readByte();
- if (bits != 8 || channels != 1) {
- warning("Unsupported VOC file format (%d bits per sample, %d channels)", bits, channels);
- break;
- }
- packing = stream.readUint16LE();
- stream.readUint32LE();
- len -= 12;
- }
- debug(9, "VOC Data Block: %d, %d, %d", rate, packing, len);
- if (packing == 0) {
- if (size) {
- ret_sound = (byte *)realloc(ret_sound, size + len);
- } else {
- ret_sound = (byte *)malloc(len);
- }
- stream.read(ret_sound + size, len);
- size += len;
- begin_loop = size;
- end_loop = size;
- } else {
- warning("VOC file packing %d unsupported", packing);
- }
- } break;
- case 3: // silence
- // occur with a few Igor sounds, voc file starts with a silence block with a
- // frequency different from the data block. Just ignore fow now (implementing
- // it wouldn't make a big difference anyway...)
- assert(len == 3);
- stream.readUint16LE();
- stream.readByte();
- break;
- case 6: // begin of loop
- assert(len == 2);
- loops = stream.readUint16LE();
- break;
- case 7: // end of loop
- assert(len == 0);
- break;
- case 8: { // "Extended"
- // This occures in the LoL Intro demo.
- // This block overwrites the next parameters of a block 1 "Sound data".
- // To assure we never get any bad data here, we will assert in case
- // this tries to define a stereo sound block or tries to use something
- // different than 8bit unsigned sound data.
- // TODO: Actually we would need to check the frequency divisor (the
- // first word) here too. It is used in the following equation:
- // sampleRate = 256000000/(channels * (65536 - frequencyDivisor))
- assert(len == 4);
- stream.readUint16LE();
- uint8 codec = stream.readByte();
- uint8 channels = stream.readByte() + 1;
- assert(codec == 0 && channels == 1);
- } break;
- default:
- warning("Unhandled code %d in VOC file (len %d)", code, len);
- return ret_sound;
- }
- }
- debug(4, "VOC Data Size : %d", size);
- return ret_sound;
-}
-
-byte *loadVOCFromStream(Common::ReadStream &stream, int &size, int &rate) {
- int loops, begin_loop, end_loop;
- return loadVOCFromStream(stream, size, rate, loops, begin_loop, end_loop);
-}
-
-
-#ifdef STREAM_AUDIO_FROM_DISK
-
-int parseVOCFormat(Common::SeekableReadStream& stream, RawStreamBlock* block, int &rate, int &loops, int &begin_loop, int &end_loop) {
- VocFileHeader fileHeader;
- int currentBlock = 0;
- int size = 0;
-
- debug(2, "parseVOCFormat");
-
- if (stream.read(&fileHeader, 8) != 8)
- goto invalid;
-
- if (!memcmp(&fileHeader, "VTLK", 4)) {
- if (stream.read(&fileHeader, sizeof(VocFileHeader)) != sizeof(VocFileHeader))
- goto invalid;
- } else if (!memcmp(&fileHeader, "Creative", 8)) {
- if (stream.read(((byte *)&fileHeader) + 8, sizeof(VocFileHeader) - 8) != sizeof(VocFileHeader) - 8)
- goto invalid;
- } else {
- invalid:;
- warning("loadVOCFromStream: Invalid header");
- return 0;
- }
-
- if (memcmp(fileHeader.desc, "Creative Voice File", 19) != 0)
- error("loadVOCFromStream: Invalid header");
- if (fileHeader.desc[19] != 0x1A)
- debug(3, "loadVOCFromStream: Partially invalid header");
-
- int32 offset = FROM_LE_16(fileHeader.datablock_offset);
- int16 version = FROM_LE_16(fileHeader.version);
- int16 code = FROM_LE_16(fileHeader.id);
- assert(offset == sizeof(VocFileHeader));
- // 0x100 is an invalid VOC version used by German version of DOTT (Disk) and
- // French version of Simon the Sorcerer 2 (CD)
- assert(version == 0x010A || version == 0x0114 || version == 0x0100);
- assert(code == ~version + 0x1234);
-
- int len;
- size = 0;
- begin_loop = 0;
- end_loop = 0;
-
- while ((code = stream.readByte())) {
- len = stream.readByte();
- len |= stream.readByte() << 8;
- len |= stream.readByte() << 16;
-
- debug(2, "Block code %d, len %d", code, len);
-
- switch (code) {
- case 1:
- case 9: {
- int packing;
- if (code == 1) {
- int time_constant = stream.readByte();
- packing = stream.readByte();
- len -= 2;
- rate = getSampleRateFromVOCRate(time_constant);
- } else {
- rate = stream.readUint32LE();
- int bits = stream.readByte();
- int channels = stream.readByte();
- if (bits != 8 || channels != 1) {
- warning("Unsupported VOC file format (%d bits per sample, %d channels)", bits, channels);
- break;
- }
- packing = stream.readUint16LE();
- stream.readUint32LE();
- len -= 12;
- }
- debug(9, "VOC Data Block: %d, %d, %d", rate, packing, len);
- if (packing == 0) {
-
- // Found a data block - so add it to the block list
- block[currentBlock].pos = stream.pos();
- block[currentBlock].len = len;
- currentBlock++;
-
- stream.seek(len, SEEK_CUR);
-
- size += len;
- begin_loop = size;
- end_loop = size;
- } else {
- warning("VOC file packing %d unsupported", packing);
- }
- } break;
- case 3: // silence
- // occur with a few Igor sounds, voc file starts with a silence block with a
- // frequency different from the data block. Just ignore fow now (implementing
- // it wouldn't make a big difference anyway...)
- assert(len == 3);
- stream.readUint16LE();
- stream.readByte();
- break;
- case 6: // begin of loop
- assert(len == 2);
- loops = stream.readUint16LE();
- break;
- case 7: // end of loop
- assert(len == 0);
- break;
- case 8: // "Extended"
- // This occures in the LoL Intro demo. This block can usually be used to create stereo
- // sound, but the LoL intro has only an empty block, thus this dummy implementation will
- // work.
- assert(len == 4);
- stream.readUint16LE();
- stream.readByte();
- stream.readByte();
- break;
- default:
- warning("Unhandled code %d in VOC file (len %d)", code, len);
- return 0;
- }
- }
- debug(4, "VOC Data Size : %d", size);
- return currentBlock;
-}
-
-AudioStream *makeVOCDiskStream(Common::SeekableReadStream *stream, byte flags, DisposeAfterUse::Flag disposeAfterUse) {
- const int MAX_AUDIO_BLOCKS = 256;
-
- RawStreamBlock *block = new RawStreamBlock[MAX_AUDIO_BLOCKS];
- int rate, loops, begin_loop, end_loop;
-
- int numBlocks = parseVOCFormat(*stream, block, rate, loops, begin_loop, end_loop);
-
- AudioStream *audioStream = 0;
-
- // Create an audiostream from the data. Note the numBlocks may be 0,
- // e.g. when invalid data is encountered. See bug #2890038.
- if (numBlocks)
- audioStream = makeRawDiskStream_OLD(stream, block, numBlocks, rate, flags, disposeAfterUse/*, begin_loop, end_loop*/);
-
- delete[] block;
-
- return audioStream;
-}
-
-SeekableAudioStream *makeVOCDiskStreamNoLoop(Common::SeekableReadStream *stream, byte flags, DisposeAfterUse::Flag disposeAfterUse) {
- const int MAX_AUDIO_BLOCKS = 256;
-
- RawStreamBlock *block = new RawStreamBlock[MAX_AUDIO_BLOCKS];
- int rate, loops, begin_loop, end_loop;
-
- int numBlocks = parseVOCFormat(*stream, block, rate, loops, begin_loop, end_loop);
-
- SeekableAudioStream *audioStream = 0;
-
- // Create an audiostream from the data. Note the numBlocks may be 0,
- // e.g. when invalid data is encountered. See bug #2890038.
- if (numBlocks)
- audioStream = makeRawDiskStream_OLD(stream, block, numBlocks, rate, flags, disposeAfterUse);
-
- delete[] block;
-
- return audioStream;
-}
-
-#endif
-
-
-AudioStream *makeVOCStream(Common::SeekableReadStream *stream, byte flags, uint loopStart, uint loopEnd, DisposeAfterUse::Flag disposeAfterUse) {
-#ifdef STREAM_AUDIO_FROM_DISK
- return makeVOCDiskStream(stream, flags, disposeAfterUse);
-#else
- int size, rate;
-
- byte *data = loadVOCFromStream(*stream, size, rate);
-
- if (!data) {
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
- return 0;
- }
-
- SeekableAudioStream *s = Audio::makeRawStream(data, size, rate, flags);
-
- if (loopStart != loopEnd) {
- const bool isStereo = (flags & Audio::FLAG_STEREO) != 0;
- const bool is16Bit = (flags & Audio::FLAG_16BITS) != 0;
-
- if (loopEnd == 0)
- loopEnd = size;
- assert(loopStart <= loopEnd);
- assert(loopEnd <= (uint)size);
-
- // Verify the buffer sizes are sane
- if (is16Bit && isStereo)
- assert((loopStart & 3) == 0 && (loopEnd & 3) == 0);
- else if (is16Bit || isStereo)
- assert((loopStart & 1) == 0 && (loopEnd & 1) == 0);
-
- const uint32 extRate = s->getRate() * (is16Bit ? 2 : 1) * (isStereo ? 2 : 1);
-
- return new SubLoopingAudioStream(s, 0, Timestamp(0, loopStart, extRate), Timestamp(0, loopEnd, extRate));
- } else {
- return s;
- }
-#endif
-}
-
-SeekableAudioStream *makeVOCStream(Common::SeekableReadStream *stream, byte flags, DisposeAfterUse::Flag disposeAfterUse) {
-#ifdef STREAM_AUDIO_FROM_DISK
- return makeVOCDiskStreamNoLoop(stream, flags, disposeAfterUse);
-#else
- int size, rate;
-
- byte *data = loadVOCFromStream(*stream, size, rate);
-
- if (!data) {
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
- return 0;
- }
-
- return makeRawStream(data, size, rate, flags);
-#endif
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/voc.h b/sound/decoders/voc.h
deleted file mode 100644
index 82cc261f2c..0000000000
--- a/sound/decoders/voc.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - drascula
- * - kyra
- * - made
- * - saga
- * - scumm
- * - touche
- */
-
-#ifndef SOUND_VOC_H
-#define SOUND_VOC_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-namespace Common { class ReadStream; }
-namespace Common { class SeekableReadStream; }
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
-struct VocFileHeader {
- uint8 desc[20];
- uint16 datablock_offset;
- uint16 version;
- uint16 id;
-} PACKED_STRUCT;
-
-struct VocBlockHeader {
- uint8 blocktype;
- uint8 size[3];
- uint8 sr;
- uint8 pack;
-} PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
-/**
- * Take a sample rate parameter as it occurs in a VOC sound header, and
- * return the corresponding sample frequency.
- *
- * This method has special cases for the standard rates of 11025 and 22050 kHz,
- * which due to limitations of the format, cannot be encoded exactly in a VOC
- * file. As a consequence, many game files have sound data sampled with those
- * rates, but the VOC marks them incorrectly as 11111 or 22222 kHz. This code
- * works around that and "unrounds" the sampling rates.
- */
-extern int getSampleRateFromVOCRate(int vocSR);
-
-/**
- * Try to load a VOC from the given stream. Returns a pointer to memory
- * containing the PCM sample data (allocated with malloc). It is the callers
- * responsibility to dellocate that data again later on! Currently this
- * function only supports uncompressed raw PCM data.
- */
-extern byte *loadVOCFromStream(Common::ReadStream &stream, int &size, int &rate);
-
-/**
- * Try to load a VOC from the given seekable stream and create an AudioStream
- * from that data. Currently this function only supports uncompressed raw PCM
- * data. Optionally supports (infinite) looping of a portion of the data.
- *
- * This function uses loadVOCFromStream() internally.
- */
-AudioStream *makeVOCStream(Common::SeekableReadStream *stream, byte flags = 0, uint loopStart = 0, uint loopEnd = 0, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::NO);
-
-/**
- * This does not use any of the looping features of VOC files!
- */
-SeekableAudioStream *makeVOCStream(Common::SeekableReadStream *stream, byte flags, DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif
diff --git a/sound/decoders/vorbis.cpp b/sound/decoders/vorbis.cpp
deleted file mode 100644
index 425eb6b751..0000000000
--- a/sound/decoders/vorbis.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-// Disable symbol overrides for FILE and fseek as those are used in the
-// Vorbis headers.
-#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
-#define FORBIDDEN_SYMBOL_EXCEPTION_fseek
-
-#include "sound/decoders/vorbis.h"
-
-#ifdef USE_VORBIS
-
-#include "common/debug.h"
-#include "common/stream.h"
-#include "common/util.h"
-
-#include "sound/audiostream.h"
-
-#ifdef USE_TREMOR
-#if defined(__GP32__) // custom libtremor locations
-#include <ivorbisfile.h>
-#else
-#include <tremor/ivorbisfile.h>
-#endif
-#else
-#include <vorbis/vorbisfile.h>
-#endif
-
-
-namespace Audio {
-
-// These are wrapper functions to allow using a SeekableReadStream object to
-// provide data to the OggVorbis_File object.
-
-static size_t read_stream_wrap(void *ptr, size_t size, size_t nmemb, void *datasource) {
- Common::SeekableReadStream *stream = (Common::SeekableReadStream *)datasource;
-
- uint32 result = stream->read(ptr, size * nmemb);
-
- return result / size;
-}
-
-static int seek_stream_wrap(void *datasource, ogg_int64_t offset, int whence) {
- Common::SeekableReadStream *stream = (Common::SeekableReadStream *)datasource;
- stream->seek((int32)offset, whence);
- return stream->pos();
-}
-
-static int close_stream_wrap(void *datasource) {
- // Do nothing -- we leave it up to the VorbisStream to free memory as appropriate.
- return 0;
-}
-
-static long tell_stream_wrap(void *datasource) {
- Common::SeekableReadStream *stream = (Common::SeekableReadStream *)datasource;
- return stream->pos();
-}
-
-static ov_callbacks g_stream_wrap = {
- read_stream_wrap, seek_stream_wrap, close_stream_wrap, tell_stream_wrap
-};
-
-
-
-#pragma mark -
-#pragma mark --- Ogg Vorbis stream ---
-#pragma mark -
-
-
-class VorbisStream : public SeekableAudioStream {
-protected:
- Common::SeekableReadStream *_inStream;
- DisposeAfterUse::Flag _disposeAfterUse;
-
- bool _isStereo;
- int _rate;
-
- Timestamp _length;
-
- OggVorbis_File _ovFile;
-
- int16 _buffer[4096];
- const int16 *_bufferEnd;
- const int16 *_pos;
-
-public:
- // startTime / duration are in milliseconds
- VorbisStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose);
- ~VorbisStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return _pos >= _bufferEnd; }
- bool isStereo() const { return _isStereo; }
- int getRate() const { return _rate; }
-
- bool seek(const Timestamp &where);
- Timestamp getLength() const { return _length; }
-protected:
- bool refill();
-};
-
-VorbisStream::VorbisStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
- _inStream(inStream),
- _disposeAfterUse(dispose),
- _length(0, 1000),
- _bufferEnd(_buffer + ARRAYSIZE(_buffer)) {
-
- int res = ov_open_callbacks(inStream, &_ovFile, NULL, 0, g_stream_wrap);
- if (res < 0) {
- warning("Could not create Vorbis stream (%d)", res);
- _pos = _bufferEnd;
- return;
- }
-
- // Read in initial data
- if (!refill())
- return;
-
- // Setup some header information
- _isStereo = ov_info(&_ovFile, -1)->channels >= 2;
- _rate = ov_info(&_ovFile, -1)->rate;
-
-#ifdef USE_TREMOR
- _length = Timestamp(ov_time_total(&_ovFile, -1), getRate());
-#else
- _length = Timestamp(uint32(ov_time_total(&_ovFile, -1) * 1000.0), getRate());
-#endif
-}
-
-VorbisStream::~VorbisStream() {
- ov_clear(&_ovFile);
- if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _inStream;
-}
-
-int VorbisStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples = 0;
- while (samples < numSamples && _pos < _bufferEnd) {
- const int len = MIN(numSamples - samples, (int)(_bufferEnd - _pos));
- memcpy(buffer, _pos, len * 2);
- buffer += len;
- _pos += len;
- samples += len;
- if (_pos >= _bufferEnd) {
- if (!refill())
- break;
- }
- }
- return samples;
-}
-
-bool VorbisStream::seek(const Timestamp &where) {
- // Vorbisfile uses the sample pair number, thus we always use "false" for the isStereo parameter
- // of the convertTimeToStreamPos helper.
- int res = ov_pcm_seek(&_ovFile, convertTimeToStreamPos(where, getRate(), false).totalNumberOfFrames());
- if (res) {
- warning("Error seeking in Vorbis stream (%d)", res);
- _pos = _bufferEnd;
- return false;
- }
-
- return refill();
-}
-
-bool VorbisStream::refill() {
- // Read the samples
- uint len_left = sizeof(_buffer);
- char *read_pos = (char *)_buffer;
-
- while (len_left > 0) {
- long result;
-
-#ifdef USE_TREMOR
- // Tremor ov_read() always returns data as signed 16 bit interleaved PCM
- // in host byte order. As such, it does not take arguments to request
- // specific signedness, byte order or bit depth as in Vorbisfile.
- result = ov_read(&_ovFile, read_pos, len_left,
- NULL);
-#else
-#ifdef SCUMM_BIG_ENDIAN
- result = ov_read(&_ovFile, read_pos, len_left,
- 1,
- 2, // 16 bit
- 1, // signed
- NULL);
-#else
- result = ov_read(&_ovFile, read_pos, len_left,
- 0,
- 2, // 16 bit
- 1, // signed
- NULL);
-#endif
-#endif
- if (result == OV_HOLE) {
- // Possibly recoverable, just warn about it
- warning("Corrupted data in Vorbis file");
- } else if (result == 0) {
- //warning("End of file while reading from Vorbis file");
- //_pos = _bufferEnd;
- //return false;
- break;
- } else if (result < 0) {
- warning("Error reading from Vorbis stream (%d)", int(result));
- _pos = _bufferEnd;
- // Don't delete it yet, that causes problems in
- // the CD player emulation code.
- return false;
- } else {
- len_left -= result;
- read_pos += result;
- }
- }
-
- _pos = _buffer;
- _bufferEnd = (int16 *)read_pos;
-
- return true;
-}
-
-
-#pragma mark -
-#pragma mark --- Ogg Vorbis factory functions ---
-#pragma mark -
-
-SeekableAudioStream *makeVorbisStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse) {
- SeekableAudioStream *s = new VorbisStream(stream, disposeAfterUse);
- if (s && s->endOfData()) {
- delete s;
- return 0;
- } else {
- return s;
- }
-}
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_VORBIS
diff --git a/sound/decoders/vorbis.h b/sound/decoders/vorbis.h
deleted file mode 100644
index 7cc395cccb..0000000000
--- a/sound/decoders/vorbis.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - draci
- * - kyra
- * - m4
- * - queen
- * - saga
- * - sci
- * - scumm
- * - sword1
- * - sword2
- * - touche
- * - tucker
- */
-
-#ifndef SOUND_VORBIS_H
-#define SOUND_VORBIS_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-#ifdef USE_VORBIS
-
-namespace Common {
- class SeekableReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-/**
- * Create a new SeekableAudioStream from the Ogg Vorbis data in the given stream.
- * Allows for seeking (which is why we require a SeekableReadStream).
- *
- * @param stream the SeekableReadStream from which to read the Ogg Vorbis data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new SeekableAudioStream, or NULL, if an error occurred
- */
-SeekableAudioStream *makeVorbisStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif // #ifdef USE_VORBIS
-#endif // #ifndef SOUND_VORBIS_H
diff --git a/sound/decoders/wave.cpp b/sound/decoders/wave.cpp
deleted file mode 100644
index fcaace5301..0000000000
--- a/sound/decoders/wave.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/debug.h"
-#include "common/util.h"
-#include "common/stream.h"
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/wave.h"
-#include "sound/decoders/adpcm.h"
-#include "sound/decoders/raw.h"
-
-namespace Audio {
-
-bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
- const int32 initialPos = stream.pos();
- byte buf[4+1];
-
- buf[4] = 0;
-
- stream.read(buf, 4);
- if (memcmp(buf, "RIFF", 4) != 0) {
- warning("getWavInfo: No 'RIFF' header");
- return false;
- }
-
- int32 wavLength = stream.readUint32LE();
-
- stream.read(buf, 4);
- if (memcmp(buf, "WAVE", 4) != 0) {
- warning("getWavInfo: No 'WAVE' header");
- return false;
- }
-
- stream.read(buf, 4);
- if (memcmp(buf, "fmt ", 4) != 0) {
- warning("getWavInfo: No 'fmt' header");
- return false;
- }
-
- uint32 fmtLength = stream.readUint32LE();
- if (fmtLength < 16) {
- // A valid fmt chunk always contains at least 16 bytes
- warning("getWavInfo: 'fmt' header is too short");
- return false;
- }
-
- // Next comes the "type" field of the fmt header. Some typical
- // values for it:
- // 1 -> uncompressed PCM
- // 17 -> IMA ADPCM compressed WAVE
- // See <http://www.saettler.com/RIFFNEW/RIFFNEW.htm> for a more complete
- // list of common WAVE compression formats...
- uint16 type = stream.readUint16LE(); // == 1 for PCM data
- uint16 numChannels = stream.readUint16LE(); // 1 for mono, 2 for stereo
- uint32 samplesPerSec = stream.readUint32LE(); // in Hz
- uint32 avgBytesPerSec = stream.readUint32LE(); // == SampleRate * NumChannels * BitsPerSample/8
-
- uint16 blockAlign = stream.readUint16LE(); // == NumChannels * BitsPerSample/8
- uint16 bitsPerSample = stream.readUint16LE(); // 8, 16 ...
- // 8 bit data is unsigned, 16 bit data signed
-
-
- if (wavType != 0)
- *wavType = type;
-
- if (blockAlign_ != 0)
- *blockAlign_ = blockAlign;
-#if 0
- debug("WAVE information:");
- debug(" total size: %d", wavLength);
- debug(" fmt size: %d", fmtLength);
- debug(" type: %d", type);
- debug(" numChannels: %d", numChannels);
- debug(" samplesPerSec: %d", samplesPerSec);
- debug(" avgBytesPerSec: %d", avgBytesPerSec);
- debug(" blockAlign: %d", blockAlign);
- debug(" bitsPerSample: %d", bitsPerSample);
-#endif
-
- if (type != 1 && type != 2 && type != 17) {
- warning("getWavInfo: only PCM, MS ADPCM or IMA ADPCM data is supported (type %d)", type);
- return false;
- }
-
- if (blockAlign != numChannels * bitsPerSample / 8 && type != 2) {
- debug(0, "getWavInfo: blockAlign is invalid");
- }
-
- if (avgBytesPerSec != samplesPerSec * blockAlign && type != 2) {
- debug(0, "getWavInfo: avgBytesPerSec is invalid");
- }
-
- // Prepare the return values.
- rate = samplesPerSec;
-
- flags = 0;
- if (bitsPerSample == 8) // 8 bit data is unsigned
- flags |= Audio::FLAG_UNSIGNED;
- else if (bitsPerSample == 16) // 16 bit data is signed little endian
- flags |= (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
- else if (bitsPerSample == 4 && (type == 2 || type == 17))
- flags |= Audio::FLAG_16BITS;
- else {
- warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
- return false;
- }
-
- if (numChannels == 2)
- flags |= Audio::FLAG_STEREO;
- else if (numChannels != 1) {
- warning("getWavInfo: unsupported number of channels %d", numChannels);
- return false;
- }
-
- // It's almost certainly a WAV file, but we still need to find its
- // 'data' chunk.
-
- // Skip over the rest of the fmt chunk.
- int offset = fmtLength - 16;
-
- do {
- stream.seek(offset, SEEK_CUR);
- if (stream.pos() >= initialPos + wavLength + 8) {
- warning("getWavInfo: Can't find 'data' chunk");
- return false;
- }
- stream.read(buf, 4);
- offset = stream.readUint32LE();
-
-#if 0
- debug(" found a '%s' tag of size %d", buf, offset);
-#endif
- } while (memcmp(buf, "data", 4) != 0);
-
- // Stream now points at 'offset' bytes of sample data...
- size = offset;
-
- return true;
-}
-
-RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
- int size, rate;
- byte flags;
- uint16 type;
- int blockAlign;
-
- if (!loadWAVFromStream(*stream, size, rate, flags, &type, &blockAlign)) {
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
- return 0;
- }
-
- if (type == 17) // MS IMA ADPCM
- return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
- else if (type == 2) // MS ADPCM
- return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMS, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
-
- // Raw PCM. Just read everything at once.
- // TODO: More elegant would be to wrap the stream.
- byte *data = (byte *)malloc(size);
- assert(data);
- stream->read(data, size);
-
- if (disposeAfterUse == DisposeAfterUse::YES)
- delete stream;
-
- return makeRawStream(data, size, rate, flags);
-}
-
-} // End of namespace Audio
diff --git a/sound/decoders/wave.h b/sound/decoders/wave.h
deleted file mode 100644
index 2bdbe8f0b6..0000000000
--- a/sound/decoders/wave.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-/**
- * @file
- * Sound decoder used in engines:
- * - agos
- * - gob
- * - mohawk
- * - saga
- * - sci
- * - scumm
- * - sword1
- * - sword2
- * - tucker
- */
-
-#ifndef SOUND_WAVE_H
-#define SOUND_WAVE_H
-
-#include "common/scummsys.h"
-#include "common/types.h"
-
-namespace Common { class SeekableReadStream; }
-
-namespace Audio {
-
-class RewindableAudioStream;
-
-/**
- * Try to load a WAVE from the given seekable stream. Returns true if
- * successful. In that case, the stream's seek position will be set to the
- * start of the audio data, and size, rate and flags contain information
- * necessary for playback. Currently this function supports uncompressed
- * raw PCM data, MS IMA ADPCM and MS ADPCM (uses makeADPCMStream internally).
- */
-extern bool loadWAVFromStream(
- Common::SeekableReadStream &stream,
- int &size,
- int &rate,
- byte &flags,
- uint16 *wavType = 0,
- int *blockAlign = 0);
-
-/**
- * Try to load a WAVE from the given seekable stream and create an AudioStream
- * from that data. Currently this function supports uncompressed
- * raw PCM data, MS IMA ADPCM and MS ADPCM (uses makeADPCMStream internally).
- *
- * This function uses loadWAVFromStream() internally.
- *
- * @param stream the SeekableReadStream from which to read the WAVE data
- * @param disposeAfterUse whether to delete the stream after use
- * @return a new RewindableAudioStream, or NULL, if an error occurred
- */
-RewindableAudioStream *makeWAVStream(
- Common::SeekableReadStream *stream,
- DisposeAfterUse::Flag disposeAfterUse);
-
-} // End of namespace Audio
-
-#endif