[Scummvm-cvs-logs] CVS: scummvm/sound adpcm.cpp,1.8.2.1,1.8.2.2 adpcm.h,1.4.2.1,1.4.2.2 wave.cpp,1.8.2.1,1.8.2.2 wave.h,1.4.2.1,1.4.2.2
Eugene Sandulenko
sev at users.sourceforge.net
Thu Oct 20 19:26:18 CEST 2005
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/scumm sound.cpp,1.479.2.2,1.479.2.3
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm actor.cpp,1.380,1.381 actor.h,1.84,1.85 akos.cpp,1.237,1.238 resource.cpp,1.344,1.345 script_v100he.cpp,2.177,2.178 script_v72he.cpp,2.310,2.311
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/scummvm/scummvm/sound
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2503/sound
Modified Files:
Tag: branch-0-8-0
adpcm.cpp adpcm.h wave.cpp wave.h
Log Message:
Backport IMA ADPCM fixes. This fixes bunch of latter HE games.
Index: adpcm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/adpcm.cpp,v
retrieving revision 1.8.2.1
retrieving revision 1.8.2.2
diff -u -d -r1.8.2.1 -r1.8.2.2
--- adpcm.cpp 18 Oct 2005 02:11:26 -0000 1.8.2.1
+++ adpcm.cpp 21 Oct 2005 02:25:20 -0000 1.8.2.2
@@ -20,9 +20,7 @@
*/
#include "common/stdafx.h"
-#include "common/stream.h"
-#include "sound/audiostream.h"
#include "sound/adpcm.h"
@@ -31,64 +29,102 @@
// See also <http://www.comptek.ru/telephony/tnotes/tt1-13.html>
//
// In addition, also IMA ADPCM is supported.
-template <typesADPCM TYPE>
-class ADPCMInputStream : public AudioStream {
-private:
- bool _evenPos;
- byte _lastByte;
- Common::SeekableReadStream *_stream;
- uint32 _endpos;
- struct adpcmStatus {
- int16 last;
- int16 stepIndex;
- } _status;
+ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels, uint32 blockAlign)
+ : _stream(stream), _channels(channels), _type(type), _blockAlign(blockAlign) {
- int16 stepAdjust(byte);
- int16 decode(byte);
+ _status.last = 0;
+ _status.stepIndex = 0;
+ _endpos = stream->pos() + size;
-public:
- ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size);
- ~ADPCMInputStream() {};
+ if (type == kADPCMIma && blockAlign == 0)
+ error("ADPCMInputStream(): blockAlign isn't specifiled for MS ADPCM IMA");
+}
- int readBuffer(int16 *buffer, const int numSamples);
+int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) {
+ switch (_type) {
+ case kADPCMOki:
+ return readBufferOKI(buffer, numSamples);
+ break;
+ case kADPCMIma:
+ if (_channels == 1)
+ return readBufferMSIMA1(buffer, numSamples);
+ else
+ return readBufferMSIMA2(buffer, numSamples);
+ break;
+ default:
+ error("Unsupported ADPCM encoding");
+ break;
+ }
+ return 0;
+}
- bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
- bool isStereo() const { return false; }
- int getRate() const { return 22050; }
-};
+int ADPCMInputStream::readBufferOKI(int16 *buffer, const int numSamples) {
+ int samples;
+ byte data;
+ assert(numSamples % 2 == 0);
-template <typesADPCM TYPE>
-ADPCMInputStream<TYPE>::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size)
- : _stream(stream), _evenPos(true) {
+ for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
+ data = _stream->readByte();
+ buffer[samples] = TO_LE_16(decodeOKI((data >> 4) & 0x0f));
+ buffer[samples + 1] = TO_LE_16(decodeOKI(data & 0x0f));
+ }
+ return samples;
+}
- _status.last = 0;
- _status.stepIndex = 0;
- _endpos = stream->pos() + size;
+
+int ADPCMInputStream::readBufferMSIMA1(int16 *buffer, const int numSamples) {
+ int samples;
+ byte data;
+ int blockLen;
+ int i;
+
+ assert(numSamples % 2 == 0);
+
+ samples = 0;
+
+ while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) {
+ // read block header
+ _status.last = _stream->readSint16LE();
+ _status.stepIndex = _stream->readSint16LE();
+
+ blockLen = MIN(_endpos - _stream->pos(), _blockAlign - 4);
+
+ for (i = 0; i < blockLen && !_stream->eos() && _stream->pos() < _endpos; i++, samples += 2) {
+ data = _stream->readByte();
+ buffer[samples] = TO_LE_16(decodeMSIMA(data & 0x0f));
+ buffer[samples + 1] = TO_LE_16(decodeMSIMA((data >> 4) & 0x0f));
+ }
+ }
+ return samples;
}
-template <typesADPCM TYPE>
-int ADPCMInputStream<TYPE>::readBuffer(int16 *buffer, const int numSamples) {
+
+// Microsoft as usual tries to implement it differently. This method
+// is used for stereo data.
+int ADPCMInputStream::readBufferMSIMA2(int16 *buffer, const int numSamples) {
int samples;
+ uint32 data;
+ int nibble;
- // Since we process high and low nibbles separately never check buffer end
- // on low nibble
- for (samples = 0; !_evenPos || samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples++) {
- if (_evenPos) {
- _lastByte = _stream->readByte();
- buffer[samples] = decode((_lastByte >> 4) & 0x0f);
- } else {
- buffer[samples] = decode(_lastByte & 0x0f);
+ 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++) {
+ byte k = ((data & 0xf0000000) >> 28);
+ buffer[samples + channel + nibble * 2] = TO_LE_16(decodeMSIMA(k));
+ data <<= 4;
+ }
}
- _evenPos = !_evenPos;
+ samples += 16;
}
return samples;
}
// adjust the step for use on the next sample.
-template <typesADPCM TYPE>
-int16 ADPCMInputStream<TYPE>::stepAdjust(byte code) {
+int16 ADPCMInputStream::stepAdjust(byte code) {
static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
return adjusts[code & 0x07];
@@ -105,8 +141,7 @@
};
// Decode Linear to ADPCM
-template <>
-int16 ADPCMInputStream<kADPCMOki>::decode(byte code) {
+int16 ADPCMInputStream::decodeOKI(byte code) {
int16 diff, E, SS, samp;
SS = okiStepSize[_status.stepIndex];
@@ -153,27 +188,27 @@
32767
};
-template <>
-int16 ADPCMInputStream<kADPCMIma>::decode(byte code) {
+int16 ADPCMInputStream::decodeMSIMA(byte code) {
int32 diff, E, SS, samp;
SS = imaStepTable[_status.stepIndex];
- E = SS/8;
- if (code & 0x01)
- E += SS/4;
- if (code & 0x02)
- E += SS/2;
+ E = SS >> 3;
if (code & 0x04)
E += SS;
+ if (code & 0x02)
+ E += SS >> 1;
+ if (code & 0x01)
+ E += SS >> 2;
diff = (code & 0x08) ? -E : E;
samp = _status.last + diff;
- if (samp < -32768)
- samp = -32768;
- else if (samp > 32767)
- samp = 32767;
+ if (samp < -0x8000)
+ samp = -0x8000;
+ else if (samp > 0x7fff)
+ samp = 0x7fff;
_status.last = samp;
+
_status.stepIndex += stepAdjust(code);
if (_status.stepIndex < 0)
_status.stepIndex = 0;
@@ -182,21 +217,3 @@
return samp;
}
-
-AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type) {
- AudioStream *audioStream;
-
- switch (type) {
- case kADPCMOki:
- audioStream = new ADPCMInputStream<kADPCMOki>(&stream, size);
- break;
- case kADPCMIma:
- audioStream = new ADPCMInputStream<kADPCMIma>(&stream, size);
- break;
- default:
- error("Unsupported ADPCM encoding");
- break;
- }
-
- return audioStream;
-}
Index: adpcm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/adpcm.h,v
retrieving revision 1.4.2.1
retrieving revision 1.4.2.2
diff -u -d -r1.4.2.1 -r1.4.2.2
--- adpcm.h 18 Oct 2005 02:11:26 -0000 1.4.2.1
+++ adpcm.h 21 Oct 2005 02:25:20 -0000 1.4.2.2
@@ -24,6 +24,8 @@
#include "common/stdafx.h"
#include "common/scummsys.h"
+#include "common/stream.h"
+#include "sound/audiostream.h"
class AudioStream;
@@ -35,6 +37,35 @@
// TODO: Switch from a SeekableReadStream to a plain ReadStream. This requires
// some internal refactoring but is definitely possible and will increase the
// flexibility of this code.
-AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type);
+class ADPCMInputStream : public AudioStream {
+private:
+ Common::SeekableReadStream *_stream;
+ uint32 _endpos;
+ int _channels;
+ typesADPCM _type;
+ uint32 _blockAlign;
+
+ struct adpcmStatus {
+ int32 last;
+ int32 stepIndex;
+ } _status;
+
+ int16 stepAdjust(byte);
+ int16 decodeOKI(byte);
+ int16 decodeMSIMA(byte);
+
+public:
+ ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type, int channels = 2, uint32 blockAlign = 0);
+ ~ADPCMInputStream() {};
+
+ int readBuffer(int16 *buffer, const int numSamples);
+ int readBufferOKI(int16 *buffer, const int numSamples);
+ int readBufferMSIMA1(int16 *buffer, const int numSamples);
+ int readBufferMSIMA2(int16 *buffer, const int numSamples);
+
+ bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
+ bool isStereo() const { return false; }
+ int getRate() const { return 22050; }
+};
#endif
Index: wave.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/wave.cpp,v
retrieving revision 1.8.2.1
retrieving revision 1.8.2.2
diff -u -d -r1.8.2.1 -r1.8.2.2
--- wave.cpp 18 Oct 2005 02:11:26 -0000 1.8.2.1
+++ wave.cpp 21 Oct 2005 02:25:20 -0000 1.8.2.2
@@ -28,7 +28,7 @@
#include "sound/wave.h"
#include "sound/adpcm.h"
-bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType) {
+bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
const uint32 initialPos = stream.pos();
byte buf[4+1];
@@ -79,6 +79,9 @@
if (wavType != 0)
*wavType = type;
+
+ if (blockAlign_ != 0)
+ *blockAlign_ = blockAlign;
#if 0
printf("WAVE information:\n");
printf(" total size: %d\n", wavLength);
@@ -161,7 +164,7 @@
return 0;
if (type == 17) // IMA ADPCM
- return makeADPCMStream(stream, size, kADPCMIma);
+ return new ADPCMInputStream(&stream, size, kADPCMIma, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1);
byte *data = (byte *)malloc(size);
assert(data);
Index: wave.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound/wave.h,v
retrieving revision 1.4.2.1
retrieving revision 1.4.2.2
diff -u -d -r1.4.2.1 -r1.4.2.2
--- wave.h 18 Oct 2005 02:11:26 -0000 1.4.2.1
+++ wave.h 21 Oct 2005 02:25:20 -0000 1.4.2.2
@@ -34,7 +34,7 @@
* all information about the data necessary for playback.
* Currently this only support uncompressed raw PCM data.
*/
-extern bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType = 0);
+extern bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType = 0, int *blockAlign = 0);
AudioStream *makeWAVStream(Common::SeekableReadStream &stream);
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/scumm sound.cpp,1.479.2.2,1.479.2.3
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm actor.cpp,1.380,1.381 actor.h,1.84,1.85 akos.cpp,1.237,1.238 resource.cpp,1.344,1.345 script_v100he.cpp,2.177,2.178 script_v72he.cpp,2.310,2.311
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Scummvm-git-logs
mailing list