diff options
-rw-r--r-- | engines/sherlock/sound.cpp | 72 | ||||
-rw-r--r-- | engines/sherlock/sound.h | 3 |
2 files changed, 47 insertions, 28 deletions
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 59098c32cc..9f36d6d9b7 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -63,29 +63,44 @@ void Sound::loadSound(const Common::String &name, int priority) { // No implementation required in ScummVM } -char Sound::decodeSample(char sample, byte& prediction, int& step) { - char diff = ((sample & 0x07) << step); - - if (sample & 0x08) { - if (prediction > diff) - prediction = prediction - ((sample & 0x07) << step); - else - prediction = 0; +static int8 creativeADPCM_ScaleMap[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 +}; + +static uint8 creativeADPCM_AdjustMap[64] = { + 0, 0, 0, 0, 0, 16, 16, 16, + 0, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 16, 16, 16, + 240, 0, 0, 0, 0, 0, 0, 0, + 240, 0, 0, 0, 0, 0, 0, 0 +}; + +byte Sound::decodeSample(byte sample, byte& reference, int16& scale) { + int16 samp = sample + scale; + int16 ref = 0; + + // clip bad ADPCM-4 sample + CLIP(samp, 0, 63); + + ref = reference + creativeADPCM_ScaleMap[samp]; + if (ref > 0xff) { + reference = 0xff; } else { - if (prediction < 0xff - diff) - prediction = prediction + ((sample&0x07) << step); - else - prediction = 0xff; - } - - - if ((sample & 0x07) >= 5 && step < 3) { - step ++; - } else if ((sample & 0x07) == 0 && step > 0) { - step --; + if (ref < 0x00) { + reference = 0; + } else { + reference = (uint8)(ref & 0xff); + } } - return prediction; + scale = (scale + creativeADPCM_AdjustMap[samp]) & 0xff; + return reference; } bool Sound::playSound(const Common::String &name, WaitType waitType, int priority) { @@ -94,7 +109,7 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit Common::String filename = name; if (!filename.contains('.')) filename += ".SND"; - + Common::SeekableReadStream *stream = _vm->_res->load(filename); if (!stream) @@ -107,16 +122,18 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit byte *ptr = data; stream->read(ptr, size); + assert(size > 2); + byte *decoded = (byte *)malloc((size - 1) * 2); - // +127 to eliminate the pop when the sound starts (signed vs unsigned PCM). Still does not help with the pop at the end - byte prediction = (ptr[0] & 0x0f) + 127; - int step = 0; + // Holmes uses Creative ADPCM 4-bit data int counter = 0; + byte reference = ptr[0]; + int16 scale = 0; for(int i = 1; i < size; i++) { - decoded[counter++] = decodeSample((ptr[i]>>4)&0x0f, prediction, step); - decoded[counter++] = decodeSample((ptr[i]>>0)&0x0f, prediction, step); + decoded[counter++] = decodeSample((ptr[i]>>4)&0x0f, reference, scale); + decoded[counter++] = decodeSample((ptr[i]>>0)&0x0f, reference, scale); } free(data); @@ -149,7 +166,7 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit break; } } while (!_vm->shouldQuit() && _mixer->isSoundHandleActive(_effectsHandle)); - + _soundPlaying = false; _mixer->stopHandle(_effectsHandle); @@ -234,3 +251,4 @@ void Sound::freeDigiSound() { } } // End of namespace Sherlock + diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 659df57bc3..4d94c58f6f 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -46,7 +46,7 @@ private: Audio::SoundHandle _effectsHandle; int _curPriority; - char decodeSample(char sample, byte& prediction, int& step); + byte decodeSample(byte sample, byte& reference, int16& scale); public: bool _digitized; bool _music; @@ -83,3 +83,4 @@ public: } // End of namespace Sherlock #endif + |