Skip to content

Commit

Permalink
SWORD1: Improve detection of speech data endianness for mac version
Browse files Browse the repository at this point in the history
Before trying an heuristic on the decoded data it simply checks if
we get the expected resource size after decompression. When
using the wrong endianness this is unlikely to be the case.
  • Loading branch information
criezy committed Jun 6, 2016
1 parent a7eb756 commit 5031885
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
31 changes: 25 additions & 6 deletions engines/sword1/sound.cpp
Expand Up @@ -124,22 +124,29 @@ void Sound::checkSpeechFileEndianness() {
uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
if (sampleSize) {
uint32 size;
bool leOk = false, beOk = false;
// Compute average of difference between two consecutive samples for both BE and LE
_bigEndianSpeech = false;
int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size, &leOk);
uint32 maxSamples = size > 2000 ? 2000 : size;
double le_diff = endiannessHeuristicValue(data, size, maxSamples);
delete[] data;
_bigEndianSpeech = true;
data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size, &beOk);
double be_diff = endiannessHeuristicValue(data, size, maxSamples);
delete [] data;
// Set the big endian flag
_bigEndianSpeech = (be_diff < le_diff);
if (leOk && !beOk)
_bigEndianSpeech = false;
else if (beOk && !leOk)
_bigEndianSpeech = true;
else
_bigEndianSpeech = (be_diff < le_diff);
if (_bigEndianSpeech)
debug(6, "Mac version: using big endian speech file");
else
debug(6, "Mac version: using little endian speech file");
debug(8, "Speech decompression memory check: big endian = %s, little endian = %s", beOk ? "good" : "bad", leOk ? "good" : "bad");
debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE (%d samples)", be_diff, le_diff, maxSamples);
}
}
Expand Down Expand Up @@ -445,7 +452,7 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
return false;
}

int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* ok) {
uint8 *fBuf = (uint8 *)malloc(cSize);
_cowFile.seek(index);
_cowFile.read(fBuf, cSize);
Expand All @@ -455,6 +462,8 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
headerPos++;

if (headerPos < 100) {
if (ok != 0)
*ok = true;
int32 resSize;
int16 *srcData;
uint32 srcPos;
Expand Down Expand Up @@ -507,8 +516,11 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
srcPos++;
if (length < 0) {
length = -length;
if (length > samplesLeft)
if (length > samplesLeft) {
length = samplesLeft;
if (ok != 0)
*ok = false;
}
int16 value;
if (_bigEndianSpeech) {
value = (int16)SWAP_BYTES_16(*((uint16 *)(srcData + srcPos)));
Expand All @@ -519,8 +531,11 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
dstData[dstPos++] = value;
srcPos++;
} else {
if (length > samplesLeft)
if (length > samplesLeft) {
length = samplesLeft;
if (ok != 0)
*ok = false;
}
if (_bigEndianSpeech) {
for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
dstData[dstPos++] = (int16)SWAP_BYTES_16(*((uint16 *)(srcData + (srcPos++))));
Expand All @@ -534,6 +549,8 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
}
if (samplesLeft > 0) {
memset(dstData + dstPos, 0, samplesLeft * 2);
if (ok != 0)
*ok = false;
}
if (_cowMode == CowDemo) // demo has wave output size embedded in the compressed data
*(uint32 *)dstData = 0;
Expand All @@ -542,6 +559,8 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) {
calcWaveVolume(dstData, resSize);
return dstData;
} else {
if (ok != 0)
*ok = false;
free(fBuf);
warning("Sound::uncompressSpeech(): DATA tag not found in wave header");
*size = 0;
Expand Down
2 changes: 1 addition & 1 deletion engines/sword1/sound.h
Expand Up @@ -110,7 +110,7 @@ class Sound {
void initCowSystem();

uint32 getSampleId(int32 fxNo);
int16 *uncompressSpeech(uint32 index, uint32 cSize, uint32 *size);
int16 *uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* ok = 0);
void calcWaveVolume(int16 *data, uint32 length);
bool _waveVolume[WAVE_VOL_TAB_LENGTH];
uint16 _waveVolPos;
Expand Down

0 comments on commit 5031885

Please sign in to comment.