diff options
| author | Paul Gilbert | 2011-04-13 21:30:26 +1000 | 
|---|---|---|
| committer | Paul Gilbert | 2011-04-13 21:30:26 +1000 | 
| commit | 4852a38f3648d7778da29402addb87590662a1ce (patch) | |
| tree | 3cbec95cfc04e10fa12660267fa25782b4c0b9d6 | |
| parent | 0600f0c018942c2a3e09b1696b2dc71b2e00d0b3 (diff) | |
| parent | 169512852e7ddf06061075e142bdb5331ed25053 (diff) | |
| download | scummvm-rg350-4852a38f3648d7778da29402addb87590662a1ce.tar.gz scummvm-rg350-4852a38f3648d7778da29402addb87590662a1ce.tar.bz2 scummvm-rg350-4852a38f3648d7778da29402addb87590662a1ce.zip | |
Merge branch 'master' of github.com:scummvm/scummvm
| -rw-r--r-- | audio/decoders/adpcm.cpp | 409 | ||||
| -rw-r--r-- | audio/decoders/adpcm.h | 7 | ||||
| -rw-r--r-- | audio/decoders/adpcm_intern.h | 230 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_codecs.cpp | 34 | ||||
| -rw-r--r-- | engines/tinsel/adpcm.cpp | 168 | ||||
| -rw-r--r-- | engines/tinsel/adpcm.h | 105 | ||||
| -rw-r--r-- | engines/tinsel/module.mk | 1 | ||||
| -rw-r--r-- | engines/tinsel/music.cpp | 5 | ||||
| -rw-r--r-- | engines/tinsel/sound.cpp | 3 | ||||
| -rw-r--r-- | engines/toon/audio.cpp | 26 | ||||
| -rw-r--r-- | video/coktel_decoder.cpp | 27 | ||||
| -rw-r--r-- | video/coktel_decoder.h | 2 | 
12 files changed, 541 insertions, 476 deletions
| diff --git a/audio/decoders/adpcm.cpp b/audio/decoders/adpcm.cpp index 7def89b688..43b5a0b3da 100644 --- a/audio/decoders/adpcm.cpp +++ b/audio/decoders/adpcm.cpp @@ -26,44 +26,12 @@  #include "common/endian.h"  #include "audio/decoders/adpcm.h" +#include "audio/decoders/adpcm_intern.h"  #include "audio/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> @@ -107,17 +75,6 @@ bool ADPCMStream::rewind() {  #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; @@ -153,7 +110,7 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {  	samp = CLIP<int16>(samp, -2048, 2047);  	_status.ima_ch[0].last = samp; -	_status.ima_ch[0].stepIndex += stepAdjust(code); +	_status.ima_ch[0].stepIndex += _stepAdjustTable[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 @@ -164,19 +121,6 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {  #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; @@ -194,34 +138,6 @@ int Ima_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {  #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); @@ -288,28 +204,6 @@ int Apple_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {  #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; @@ -382,41 +276,6 @@ static const int MSADPCMAdaptationTable[] = {  }; -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; @@ -478,246 +337,9 @@ int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {  } -  #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) { \ @@ -782,14 +404,15 @@ int DK3_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {  #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]; -} +// This table is used to adjust the step for use on the next sample. +// We could half the table, but since the lookup index used is always +// a 4-bit nibble, it's more efficient to just keep it as it is. +const int16 ADPCMStream::_stepAdjustTable[16] = { +	-1, -1, -1, -1, 2, 4, 6, 8, +	-1, -1, -1, -1, 2, 4, 6, 8 +}; -static const uint16 imaStepTable[89] = { +const int16 Ima_ADPCMStream::_imaTable[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, @@ -805,13 +428,13 @@ static const uint16 imaStepTable[89] = {  };  int16 Ima_ADPCMStream::decodeIMA(byte code, int channel) { -	int32 E = (2 * (code & 0x7) + 1) * imaStepTable[_status.ima_ch[channel].stepIndex] / 8; +	int32 E = (2 * (code & 0x7) + 1) * _imaTable[_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); +	_status.ima_ch[channel].stepIndex += _stepAdjustTable[code]; +	_status.ima_ch[channel].stepIndex = CLIP<int32>(_status.ima_ch[channel].stepIndex, 0, ARRAYSIZE(_imaTable) - 1);  	return samp;  } @@ -830,12 +453,6 @@ RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, Dispo  		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: diff --git a/audio/decoders/adpcm.h b/audio/decoders/adpcm.h index 38ec870a27..06cda69225 100644 --- a/audio/decoders/adpcm.h +++ b/audio/decoders/adpcm.h @@ -38,7 +38,9 @@  #define SOUND_ADPCM_H  #include "common/scummsys.h" -#include "common/stream.h" +#include "common/types.h" + +namespace Common { class SeekableReadStream; }  namespace Audio { @@ -56,9 +58,6 @@ enum typesADPCM {  	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 diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h new file mode 100644 index 0000000000..b566f2c765 --- /dev/null +++ b/audio/decoders/adpcm_intern.h @@ -0,0 +1,230 @@ +/* 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$ + * + */ + +/** + * Internal interfaces to the ADPCM encoders. + * + * These can be used to make custom ADPCM decoder subclasses, + * or to at least share some common data tables between various + * ADPCM decoder implementations. + */ + +#ifndef SOUND_ADPCM_INTERN_H +#define SOUND_ADPCM_INTERN_H + +#include "audio/audiostream.h" +#include "common/endian.h" +#include "common/stream.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(); + +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(); + + +	/** +	 * This table is used by some ADPCM variants (IMA and OKI) to adjust the +	 * step for use on the next sample. +	 * The first 8 entries are identical to the second 8 entries. Hence, we +	 * could half the table in size. But since the lookup index is always a +	 * 4-bit nibble, it is more efficient to just keep it as it is. +	 */ +	static const int16 _stepAdjustTable[16]; +}; + +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); +}; + +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); + + +	/** +	 * This table is used by decodeIMA. +	 */ +	static const int16 _imaTable[89]; +}; + +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); + +}; + +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 +}; + +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); +}; + +// 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; +}; + +} // End of namespace Audio + +#endif diff --git a/engines/scumm/imuse_digi/dimuse_codecs.cpp b/engines/scumm/imuse_digi/dimuse_codecs.cpp index f526530405..fd9deb7b44 100644 --- a/engines/scumm/imuse_digi/dimuse_codecs.cpp +++ b/engines/scumm/imuse_digi/dimuse_codecs.cpp @@ -27,6 +27,8 @@  #include "common/util.h"  #include "scumm/imuse_digi/dimuse_codecs.h" +#include "audio/decoders/adpcm_intern.h" +  namespace Scumm {  namespace BundleCodecs { @@ -63,21 +65,7 @@ uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size) {  static byte *_destImcTable = NULL;  static uint32 *_destImcTable2 = NULL; -static const int16 imcTable[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 -}; - +// This table is the "big brother" of Audio::ADPCMStream::_stepAdjustTable.  static const byte imxOtherTable[6][64] = {  	{  		0xFF, @@ -131,7 +119,7 @@ void initializeImcTables() {  	for (pos = 0; pos <= 88; ++pos) {  		byte put = 1; -		int32 tableValue = ((imcTable[pos] * 4) / 7) / 2; +		int32 tableValue = ((Audio::Ima_ADPCMStream::_imaTable[pos] * 4) / 7) / 2;  		while (tableValue != 0) {  			tableValue /= 2;  			put++; @@ -149,7 +137,7 @@ void initializeImcTables() {  		for (pos = 0; pos <= 88; ++pos) {  			int32 count = 32;  			int32 put = 0; -			int32 tableValue = imcTable[pos]; +			int32 tableValue = Audio::Ima_ADPCMStream::_imaTable[pos];  			do {  				if ((count & n) != 0) {  					put += tableValue; @@ -304,7 +292,7 @@ int32 decompressADPCM(byte *compInput, byte *compOutput, int channels) {  			const byte data = (packet & dataBitMask);  			const int32 tmpA = (data << (7 - curTableEntryBitCount)); -			const int32 imcTableEntry = imcTable[curTablePos] >> (curTableEntryBitCount - 1); +			const int32 imcTableEntry = Audio::Ima_ADPCMStream::_imaTable[curTablePos] >> (curTableEntryBitCount - 1);  			int32 delta = imcTableEntry + _destImcTable2[tmpA + (curTablePos * 64)];  			// The topmost bit in the data packet tells is a sign bit @@ -316,19 +304,13 @@ int32 decompressADPCM(byte *compInput, byte *compOutput, int channels) {  			outputWord += delta;  			// Clip outputWord to 16 bit signed, and write it into the destination stream -			if (outputWord > 0x7fff) -				outputWord = 0x7fff; -			if (outputWord < -0x8000) -				outputWord = -0x8000; +			outputWord = CLIP<int32>(outputWord, -0x8000, 0x7fff);  			WRITE_BE_UINT16(dst + destPos, outputWord);  			destPos += channels << 1;  			// Adjust the curTablePos  			curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data]; -			if (curTablePos < 0) -				curTablePos = 0; -			else if (curTablePos >= ARRAYSIZE(imcTable)) -				curTablePos = ARRAYSIZE(imcTable) - 1; +			curTablePos = CLIP<int32>(curTablePos, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1);  		}  	} diff --git a/engines/tinsel/adpcm.cpp b/engines/tinsel/adpcm.cpp new file mode 100644 index 0000000000..ec51d150dc --- /dev/null +++ b/engines/tinsel/adpcm.cpp @@ -0,0 +1,168 @@ +/* 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 "tinsel/adpcm.h" + +namespace Tinsel { + +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); +} + +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; +} + +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; +} + +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; +} + + +} // End of namespace Tinsel diff --git a/engines/tinsel/adpcm.h b/engines/tinsel/adpcm.h new file mode 100644 index 0000000000..79d537eef6 --- /dev/null +++ b/engines/tinsel/adpcm.h @@ -0,0 +1,105 @@ +/* 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 TINSEL_ADPCM_H +#define TINSEL_ADPCM_H + +#include "audio/decoders/adpcm_intern.h" + +namespace Tinsel { + +class Tinsel_ADPCMStream : public Audio::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)); +	} + +}; + +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); +}; + +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); +}; + +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); +}; + + +} // End of namespace Tinsel + +#endif diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk index 2778cec3df..2ab94b830a 100644 --- a/engines/tinsel/module.mk +++ b/engines/tinsel/module.mk @@ -2,6 +2,7 @@ MODULE := engines/tinsel  MODULE_OBJS := \  	actors.o \ +	adpcm.o \  	anim.o \  	background.o \  	bg.o \ diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index 49eacce9ae..12bcff829b 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -38,6 +38,7 @@  #include "common/file.h"  #include "common/memstream.h" +#include "tinsel/adpcm.h"  #include "tinsel/config.h"  #include "tinsel/sound.h"  #include "tinsel/music.h" @@ -785,8 +786,8 @@ bool PCMMusicPlayer::getNextChunk() {  		sampleStream = new Common::MemoryReadStream(buffer, sampleCLength, DisposeAfterUse::YES);  		delete _curChunk; -		_curChunk = makeADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength, -				Audio::kADPCMTinsel8, 22050, 1, 32); +		_curChunk = new Tinsel8_ADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength, +				22050, 1, 32);  		_state = S_MID;  		return true; diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index a76d26eade..1fcdb4dcf9 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -26,6 +26,7 @@  #include "tinsel/sound.h" +#include "tinsel/adpcm.h"  #include "tinsel/dw.h"  #include "tinsel/config.h"  #include "tinsel/music.h" @@ -319,7 +320,7 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p  #endif  		break;  	default: -		sampleStream = Audio::makeADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); +		sampleStream = new Tinsel6_ADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, 22050, 1, 24);  		break;  	} diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp index 0003bb1972..c2e0bf7b20 100644 --- a/engines/toon/audio.cpp +++ b/engines/toon/audio.cpp @@ -26,24 +26,10 @@  #include "toon/audio.h"  #include "common/memstream.h"  #include "common/substream.h" +#include "audio/decoders/adpcm_intern.h"  namespace Toon { -static const int ADPCM_index[8] = { -	-1, -1, -1, -1, 2 , 4 , 6 , 8 -}; -static const int ADPCM_table[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 -}; -  AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {  	for (int32 i = 0; i < 16; i++)  		_channels[i] = NULL; @@ -372,7 +358,7 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize  		int32 v31 = v30 & 0x8;  		int32 v32 = v30 & 0x7; -		int32 v33 = ADPCM_table[v19]; +		int32 v33 = Audio::Ima_ADPCMStream::_imaTable[v19];  		int32 v34 = v33 >> 3;  		if (v32 & 4)  			v34 += v33; @@ -383,12 +369,8 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize  		if (v32 & 1)  			v34 += v33 >> 2; -		v19 += ADPCM_index[v32]; -		if (v19 < 0) -			v19 = 0; - -		if (v19 > 88) -			v19 = 88; +		v19 += Audio::ADPCMStream::_stepAdjustTable[v32]; +		v19 = CLIP<int32>(v19, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1);  		if (v31)  			v18 -= v34; diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp index a755d18bb0..0ab12e91cc 100644 --- a/video/coktel_decoder.cpp +++ b/video/coktel_decoder.cpp @@ -34,6 +34,7 @@  #include "audio/audiostream.h"  #include "audio/decoders/raw.h" +#include "audio/decoders/adpcm_intern.h"  #include "common/memstream.h"  static const uint32 kVideoCodecIndeo3 = MKTAG('i','v','3','2'); @@ -1516,26 +1517,6 @@ const uint16 VMDDecoder::_tableDPCM[128] = {  	0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000  }; -const int32 VMDDecoder::_tableADPCM[] = { -			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,     0 -}; - -const int32 VMDDecoder::_tableADPCMStep[] = { -	-1, -1, -1, -1, 2,  4,  6,  8, -	-1, -1, -1, -1, 2,  4,  6,  8 -}; -  VMDDecoder::VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : CoktelDecoder(mixer, soundType),  	_stream(0), _version(0), _flags(0), _frameInfoOffset(0), _partsPerFrame(0), _frames(0),  	_soundFlags(0), _soundFreq(0), _soundSliceSize(0), _soundSlicesCount(0), @@ -2617,7 +2598,7 @@ byte *VMDDecoder::deADPCM(const byte *data, uint32 &size, int32 init, int32 inde  	index = CLIP<int32>(index, 0, 88); -	int32 predictor = _tableADPCM[index]; +	int32 predictor = Audio::Ima_ADPCMStream::_imaTable[index];  	uint32 dataByte = 0;  	bool newByte = true; @@ -2634,7 +2615,7 @@ byte *VMDDecoder::deADPCM(const byte *data, uint32 &size, int32 init, int32 inde  		newByte = !newByte; -		index += _tableADPCMStep[code]; +		index += Audio::ADPCMStream::_stepAdjustTable[code];  		index  = CLIP<int32>(index, 0, 88);  		int32 value = predictor / 8; @@ -2653,7 +2634,7 @@ byte *VMDDecoder::deADPCM(const byte *data, uint32 &size, int32 init, int32 inde  		init = CLIP<int32>(init, -32768, 32767); -		predictor = _tableADPCM[index]; +		predictor = Audio::Ima_ADPCMStream::_imaTable[index];  		*out++ = TO_BE_16(init);  	} diff --git a/video/coktel_decoder.h b/video/coktel_decoder.h index 9c8263be9d..e83e1d29ed 100644 --- a/video/coktel_decoder.h +++ b/video/coktel_decoder.h @@ -431,8 +431,6 @@ private:  	// Tables for the audio decompressors  	static const uint16 _tableDPCM[128]; -	static const int32  _tableADPCM[]; -	static const int32  _tableADPCMStep[];  	Common::SeekableReadStream *_stream; | 
