- Implemented sound decompression for Manhole EGA

svn-id: r36048
This commit is contained in:
Benjamin Haisch 2009-01-25 01:58:16 +00:00
parent b93db9f30f
commit 6297561f7c
4 changed files with 147 additions and 10 deletions

View File

@ -112,7 +112,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_soundRate = 11025;
break;
case GID_MANHOLE:
_soundRate = getVersion() == 2 ? 11025 : 4000;
_soundRate = 11025;
break;
case GID_LGOP2:
_soundRate = 8000;
@ -249,6 +249,23 @@ void MadeEngine::handleEvents() {
Common::Error MadeEngine::go() {
/*
byte source[200000], dest[500000];
int size;
FILE *f = fopen("Q:\\OldGames\\scummvm\\00000003.snd", "rb");
size = fread(source, 1, 200000, f);
fclose(f);
ManholeEgaSoundDecompressor dec;
dec.decompress(source, dest, size);
FILE *x = fopen("Q:\\OldGames\\scummvm\\test.0", "wb");
fwrite(dest, size * 4, 1, x);
fclose(x);
return Common::kNoError;
*/
resetAllTimers();
if (getGameID() == GID_RTZ) {

View File

@ -265,16 +265,10 @@ Audio::AudioStream *SoundResource::getAudioStream(int soundRate, bool loop) {
}
void SoundResourceV1::load(byte *source, int size) {
// TODO: This is all wrong. Seems like the sound is compressed
// but where is the compression info? (chunks, chunk size)
_soundSize = size;
_soundSize = size * 4;
_soundData = new byte[_soundSize];
// TODO: We set the audio to silent for now
//memcpy(_soundData, source, _soundSize);
memset(_soundData, 0x80, _soundSize);
ManholeEgaSoundDecompressor dec;
dec.decompress(source, _soundData, size);
}
/* MenuResource */

View File

@ -31,6 +31,113 @@
namespace Made {
void ManholeEgaSoundDecompressor::decompress(byte *source, byte *dest, uint32 size) {
/* Some kind of ADPCM compression. I hope this works on BE machines. */
int newmode;
_source = source;
_dest = dest;
_size = size;
_bitBuffer = 0;
_bitsLeft = 0;
_writeFlag = false;
_eof = false;
_sample1 = 0x80000;
_sample2 = 0x800000;
_sample3 = 0x800000;
_sample4 = 0x800000;
_mode = getBit();
while (!_eof) {
update1();
update3();
update0();
newmode = getBit();
if (_eof)
break;
if (newmode == _mode) {
update1();
update3();
do {
update0();
newmode = getBit();
if (_eof || newmode != _mode)
break;
update2();
update3();
} while (1);
}
_mode = newmode;
}
}
int ManholeEgaSoundDecompressor::getBit() {
if (_bitsLeft == 0) {
if (_size == 0) {
_eof = true;
return 0;
}
_bitBuffer = READ_BE_UINT16(_source);
_source += 2;
_bitsLeft = 16;
_size -= 2;
}
int temp = _bitBuffer & 0x8000;
_bitBuffer <<= 1;
_bitsLeft--;
return temp;
}
void ManholeEgaSoundDecompressor::update0() {
SWAP(_sample1, _sample3);
if (_sample2 & 0x80000000) {
_sample2 -= (_sample2 >> 8) | 0xFF000000;
} else {
_sample2 -= _sample2 >> 8;
}
_sample2 += 0x8000;
if (_sample2 & 0x80000000) {
_sample2 = 0;
} else if ((_sample2 & 0xFFFF0000) > 0x00FF0000) {
_sample2 = 0xFF0000;
}
_sample1 += _sample2;
_sample1 >>= 1;
_sample1 -= _sample4;
_sample1 >>= 2;
_sample4 += _sample1;
if (_writeFlag) {
*_dest++ = (_sample4 & 0xFF0000) >> 16;
}
_writeFlag = !_writeFlag;
_sample1 = _sample2;
SWAP(_sample1, _sample3);
}
void ManholeEgaSoundDecompressor::update1() {
if (_sample1 & 0x80000000) {
_sample1 -= (_sample1 >> 8) | 0xFF000000;
} else {
_sample1 -= _sample1 >> 8;
}
_sample1 += 500;
}
void ManholeEgaSoundDecompressor::update2() {
uint32 temp = (_sample1 >> 6) | ((_sample1 & 0xFF) << 27) | ((_sample1 & 0xC0) >> 5);
if (_sample1 & 0x80000000) {
_sample1 += temp | 0xFC000000;
} else {
_sample1 += temp & 0x03FFFFFF;
}
_sample1 += 500;
}
void ManholeEgaSoundDecompressor::update3() {
if (_mode)
_sample2 -= _sample1;
else
_sample2 += _sample1;
}
void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray) {
int16 prevSample = 0, workSample = 0;

View File

@ -33,6 +33,25 @@
namespace Made {
class ManholeEgaSoundDecompressor {
public:
void decompress(byte *source, byte *dest, uint32 size);
protected:
byte *_source, *_dest;
uint32 _size;
uint16 _bitBuffer;
int _bitsLeft;
int32 _sample1, _sample2, _sample3, _sample4;
bool _writeFlag;
bool _eof;
int _mode;
int getBit();
void update0();
void update1();
void update2();
void update3();
};
struct SoundEnergyItem {
uint32 position;
byte energy;