mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-05 00:36:57 +00:00
o Fixed ADPCM decoder length bug
o Plugged IMA ADPCM into SCUMM engine so latter HE titles now have speech though it is somewhat noisy don't know why as decoder is based on ADPCM reference implementation. svn-id: r17904
This commit is contained in:
parent
a71d60686c
commit
575e94602c
@ -119,7 +119,7 @@ int Sound::playVoxVoice(SOUNDBUFFER *buf) {
|
||||
|
||||
_voxStream = new Common::MemoryReadStream(buf->s_buf, buf->s_buf_len);
|
||||
|
||||
audioStream = makeADPCMStream(*_voxStream, kADPCMOki);
|
||||
audioStream = makeADPCMStream(*_voxStream, buf->s_buf_len, kADPCMOki);
|
||||
_mixer->playInputStream(SoundMixer::kSFXSoundType, &_voiceHandle, audioStream);
|
||||
|
||||
return SUCCESS;
|
||||
|
@ -33,6 +33,7 @@ private:
|
||||
bool _evenPos;
|
||||
Common::SeekableReadStream *_stream;
|
||||
typesADPCM _type;
|
||||
uint32 _endpos;
|
||||
|
||||
struct adpcmStatus {
|
||||
int16 last;
|
||||
@ -47,22 +48,23 @@ private:
|
||||
int readIMABuffer(int16 *buffer, const int numSamples);
|
||||
|
||||
public:
|
||||
ADPCMInputStream(Common::SeekableReadStream *stream, typesADPCM type);
|
||||
ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type);
|
||||
~ADPCMInputStream() {};
|
||||
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
|
||||
bool endOfData() const { return _stream->eos(); }
|
||||
bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
|
||||
bool isStereo() const { return false; }
|
||||
int getRate() const { return 22050; }
|
||||
};
|
||||
|
||||
|
||||
ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, typesADPCM type)
|
||||
ADPCMInputStream::ADPCMInputStream(Common::SeekableReadStream *stream, uint32 size, typesADPCM type)
|
||||
: _stream(stream), _evenPos(true), _type(type) {
|
||||
|
||||
_status.last = 0;
|
||||
_status.stepIndex = 0;
|
||||
_endpos = stream->pos() + size;
|
||||
}
|
||||
|
||||
int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||
@ -83,7 +85,7 @@ int ADPCMInputStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||
int ADPCMInputStream::readOkiBuffer(int16 *buffer, const int numSamples) {
|
||||
int samples;
|
||||
|
||||
for (samples = 0; samples < numSamples && !_stream->eos(); samples++) {
|
||||
for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples++) {
|
||||
// * 16 effectively converts 12-bit input to 16-bit output
|
||||
if (_evenPos) {
|
||||
buffer[samples] = okiADPCMDecode((_stream->readByte() >> 4) & 0x0f) * 16;
|
||||
@ -100,7 +102,7 @@ int ADPCMInputStream::readOkiBuffer(int16 *buffer, const int numSamples) {
|
||||
int ADPCMInputStream::readIMABuffer(int16 *buffer, const int numSamples) {
|
||||
int samples;
|
||||
|
||||
for (samples = 0; samples < numSamples && !_stream->eos(); samples++) {
|
||||
for (samples = 0; samples < numSamples && !_stream->eos() && _stream->pos() < _endpos; samples++) {
|
||||
if (_evenPos) {
|
||||
buffer[samples] = imaADPCMDecode((_stream->readByte() >> 4) & 0x0f);
|
||||
// Rewind back so we will reget byte later
|
||||
@ -161,8 +163,8 @@ int16 ADPCMInputStream::okiADPCMDecode(byte code) {
|
||||
return samp;
|
||||
}
|
||||
|
||||
AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, typesADPCM type) {
|
||||
AudioStream *audioStream = new ADPCMInputStream(&stream, type);
|
||||
AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type) {
|
||||
AudioStream *audioStream = new ADPCMInputStream(&stream, size, type);
|
||||
|
||||
return audioStream;
|
||||
}
|
||||
@ -183,12 +185,10 @@ static const uint16 imaStepTable[89] = {
|
||||
32767
|
||||
};
|
||||
|
||||
|
||||
int16 ADPCMInputStream::imaADPCMDecode(byte code) {
|
||||
int diff, E, SS, samp;
|
||||
int32 diff, E, SS, samp;
|
||||
|
||||
SS = imaStepTable[_status.stepIndex];
|
||||
|
||||
E = SS/8;
|
||||
if (code & 0x01)
|
||||
E += SS/4;
|
||||
@ -196,13 +196,14 @@ int16 ADPCMInputStream::imaADPCMDecode(byte code) {
|
||||
E += SS/2;
|
||||
if (code & 0x04)
|
||||
E += SS;
|
||||
|
||||
diff = (code & 0x08) ? -E : E;
|
||||
samp = _status.last + diff;
|
||||
|
||||
if(samp < -0x8000)
|
||||
samp = -0x8000;
|
||||
else if(samp > 0x7fff)
|
||||
samp = 0x7fff;
|
||||
if(samp < -32768)
|
||||
samp = -32768;
|
||||
else if(samp > 32767)
|
||||
samp = 32767;
|
||||
|
||||
_status.last = samp;
|
||||
_status.stepIndex += stepAdjust(code);
|
||||
|
@ -32,6 +32,6 @@ enum typesADPCM {
|
||||
kADPCMIma
|
||||
};
|
||||
|
||||
AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, typesADPCM type);
|
||||
AudioStream *makeADPCMStream(Common::SeekableReadStream &stream, uint32 size, typesADPCM type);
|
||||
|
||||
#endif
|
||||
|
@ -26,8 +26,9 @@
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/wave.h"
|
||||
#include "sound/adpcm.h"
|
||||
|
||||
bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags) {
|
||||
bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType) {
|
||||
const uint32 initialPos = stream.pos();
|
||||
byte buf[4+1];
|
||||
|
||||
@ -62,7 +63,8 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
|
||||
// Next comes the "type" field of the fmt header. Some typical
|
||||
// values for it:
|
||||
// 1 -> uncompressed PCM
|
||||
// 1 -> uncompressed PCM
|
||||
// 17 -> IMA ADPCM compressed WAVE
|
||||
// See <http://www.sonicspot.com/guide/wavefiles.html> for a more complete
|
||||
// list of common WAVE compression formats...
|
||||
uint16 type = stream.readUint16LE(); // == 1 for PCM data
|
||||
@ -74,6 +76,9 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
uint16 bitsPerSample = stream.readUint16LE(); // 8, 16 ...
|
||||
// 8 bit data is unsigned, 16 bit data signed
|
||||
|
||||
|
||||
if (wavType != 0)
|
||||
*wavType = type;
|
||||
#if 0
|
||||
printf("WAVE information:\n");
|
||||
printf(" total size: %d\n", wavLength);
|
||||
@ -86,8 +91,8 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
printf(" bitsPerSample: %d\n", bitsPerSample);
|
||||
#endif
|
||||
|
||||
if (type != 1) {
|
||||
warning("getWavInfo: only PCM data is supported (type %d)", type);
|
||||
if (type != 1 && type != 17) {
|
||||
warning("getWavInfo: only PCM or IMA ADPCM data is supported (type %d)", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -107,6 +112,8 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
flags |= SoundMixer::FLAG_UNSIGNED;
|
||||
else if (bitsPerSample == 16) // 16 bit data is signed little endian
|
||||
flags |= (SoundMixer::FLAG_16BITS | SoundMixer::FLAG_LITTLE_ENDIAN);
|
||||
else if (bitsPerSample == 4 && type == 17) // IDA ADPCM compressed. We decompress it
|
||||
flags |= (SoundMixer::FLAG_16BITS | SoundMixer::FLAG_LITTLE_ENDIAN);
|
||||
else {
|
||||
warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
|
||||
return false;
|
||||
@ -148,10 +155,14 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
AudioStream *makeWAVStream(Common::SeekableReadStream &stream) {
|
||||
int size, rate;
|
||||
byte flags;
|
||||
uint16 type;
|
||||
|
||||
if (!loadWAVFromStream(stream, size, rate, flags))
|
||||
if (!loadWAVFromStream(stream, size, rate, flags, &type))
|
||||
return 0;
|
||||
|
||||
if (type == 17) // IMA ADPCM
|
||||
return makeADPCMStream(stream, size, kADPCMIma);
|
||||
|
||||
byte *data = (byte *)malloc(size);
|
||||
assert(data);
|
||||
stream.read(data, size);
|
||||
|
@ -34,7 +34,7 @@ namespace Common { class SeekableReadStream; }
|
||||
* 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);
|
||||
extern bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType = 0);
|
||||
|
||||
AudioStream *makeWAVStream(Common::SeekableReadStream &stream);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user