SHERLOCK: Better decoding of ADPCM 4bit sounds, courtesy of m_kiewitz
This commit is contained in:
parent
e909f1325f
commit
239562fc01
2 changed files with 46 additions and 27 deletions
|
@ -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);
|
||||
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
|
||||
};
|
||||
|
||||
if (sample & 0x08) {
|
||||
if (prediction > diff)
|
||||
prediction = prediction - ((sample & 0x07) << step);
|
||||
else
|
||||
prediction = 0;
|
||||
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 (ref < 0x00) {
|
||||
reference = 0;
|
||||
} else {
|
||||
reference = (uint8)(ref & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((sample & 0x07) >= 5 && step < 3) {
|
||||
step ++;
|
||||
} else if ((sample & 0x07) == 0 && step > 0) {
|
||||
step --;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue