[Scummvm-cvs-logs] SF.net SVN: scummvm:[42423] scummvm/trunk/engines/sword1

sev at users.sourceforge.net sev at users.sourceforge.net
Sun Jul 12 20:52:38 CEST 2009


Revision: 42423
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42423&view=rev
Author:   sev
Date:     2009-07-12 18:52:38 +0000 (Sun, 12 Jul 2009)

Log Message:
-----------
Patch #1936137: "Speech for Mac BS1 english"

Modified Paths:
--------------
    scummvm/trunk/engines/sword1/sound.cpp
    scummvm/trunk/engines/sword1/sound.h
    scummvm/trunk/engines/sword1/sword1.cpp

Modified: scummvm/trunk/engines/sword1/sound.cpp
===================================================================
--- scummvm/trunk/engines/sword1/sound.cpp	2009-07-12 16:59:29 UTC (rev 42422)
+++ scummvm/trunk/engines/sword1/sound.cpp	2009-07-12 18:52:38 UTC (rev 42423)
@@ -51,6 +51,7 @@
 	strcpy(_filePath, searchPath);
 	_mixer = mixer;
 	_resMan = pResMan;
+	_bigEndianSpeech = false;
 	_cowHeader = NULL;
 	_endOfQueue = 0;
 	_currentCowFile = 0;
@@ -67,6 +68,83 @@
 	closeCowSystem();
 }
 
+void Sound::checkSpeechFileEndianness() {
+	// Some mac versions (not all of them) use big endian wav, although
+	// the wav header doesn't indicate it.
+	// Use heuristic to determine endianness of speech.
+	// The heuristic consist in computing the sum of the absolute difference for
+	// every two consecutive samples. This is done both with a big endian and a
+	// little endian assumption. The one with the smallest sum should be the
+	// correct one (the sound wave is supposed to be relatively smooth).
+	// It needs at least 1000 samples to get stable result (the code below is
+	// using the first 2000 samples of the wav sound.
+
+	// Init speach file if not already done.
+	if (!_currentCowFile) {
+		// Open one of the speech file. It uses SwordEngine::_systemVars.currentCD
+		// to decide which file to open, therefore if it is currently set to zero
+		// we have to set it to either 1 or 2 (I decided to set it to 1 as this is
+		// more likely to be the first file that will be needed).
+		bool no_current_cd = false;
+		if (SwordEngine::_systemVars.currentCD == 0) {
+			SwordEngine::_systemVars.currentCD = 1;
+			no_current_cd = true;
+		}
+		initCowSystem();
+		if (no_current_cd) {
+			// In case it fails with CD1 retyr with CD2
+			if (!_currentCowFile) {
+				SwordEngine::_systemVars.currentCD = 2;
+				initCowSystem();
+			}
+			// Reset curentCD flag
+			SwordEngine::_systemVars.currentCD = 0;
+		}
+	}
+
+	// Testing for endianness makes sense only if using the nom compressed files.
+	if (_cowHeader == NULL || (_cowMode != CowWave && _cowMode != CowDemo))
+		return;
+
+	// I picked the sample to use randomly (I just made sure it is long enough so that there is
+	// a fair change of the heuristic to have a stable result and work for every languages).
+	int roomNo = _currentCowFile == 1 ? 1 : 129;
+	int localNo = _currentCowFile == 1 ? 2 : 933;
+	// Get the speech data and apply the heuristic
+	uint32 locIndex = _cowHeader[roomNo] >> 2;
+	uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)];
+	uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
+	if (sampleSize) {
+		uint32 size;
+		double be_diff_sum = 0., le_diff_sum = 0.;
+		_bigEndianSpeech = false;
+		int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
+		// Compute average of differecen between two consecutive samples for both BE and LE
+		if (data) {
+			if (size > 4000)
+				size = 2000;
+			else
+				size /= 2;
+			int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16*)(data)));
+			for (uint32 i = 1 ; i < size ; ++i) {
+				le_diff_sum += fabs(data[i] - data[i-1]);
+				int16 be_value = (int16)SWAP_BYTES_16(*((uint16*)(data + i)));
+				be_diff_sum += fabs(be_value - prev_be_value);
+				prev_be_value = be_value;
+			}
+			delete [] data;
+		}
+		// Set the big endian flag
+		_bigEndianSpeech = (be_diff_sum < le_diff_sum);
+		if (_bigEndianSpeech)
+			debug(6, "Mac version: using big endian speech file");
+		else
+			debug(6, "Mac version: using little endian speech file");
+		debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size);
+	}
+}
+
+
 int Sound::addToQueue(int32 fxNo) {
 	bool alreadyInQueue = false;
 	for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++)
@@ -386,21 +464,32 @@
 		int16 *dstData = (int16*)malloc(resSize * 2);
 		int32 samplesLeft = resSize;
 		while (srcPos < cSize && samplesLeft > 0) {
-			length = (int16)READ_LE_UINT16(srcData + srcPos);
+			length = (int16)(_bigEndianSpeech ? READ_BE_UINT16(srcData + srcPos) : READ_LE_UINT16(srcData + srcPos));
 			srcPos++;
 			if (length < 0) {
 				length = -length;
 				if (length > samplesLeft)
 					length = samplesLeft;
+				int16 value;
+				if (_bigEndianSpeech) {
+					value = (int16)SWAP_BYTES_16(*((uint16*)(srcData + srcPos)));
+				} else {
+					value = srcData[srcPos];
+				}
 				for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
-					dstData[dstPos++] = srcData[srcPos];
+					dstData[dstPos++] = value;
 				srcPos++;
 			} else {
 				if (length > samplesLeft)
 					length = samplesLeft;
-				memcpy(dstData + dstPos, srcData + srcPos, length * 2);
-				dstPos += length;
-				srcPos += length;
+				if (_bigEndianSpeech) {
+					for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
+						dstData[dstPos++] = (int16)SWAP_BYTES_16(*((uint16*)(srcData + (srcPos++))));
+				} else {
+					memcpy(dstData + dstPos, srcData + srcPos, length * 2);
+					dstPos += length;
+					srcPos += length;
+				}
 			}
 			samplesLeft -= length;
 		}

Modified: scummvm/trunk/engines/sword1/sound.h
===================================================================
--- scummvm/trunk/engines/sword1/sound.h	2009-07-12 16:59:29 UTC (rev 42422)
+++ scummvm/trunk/engines/sword1/sound.h	2009-07-12 18:52:38 UTC (rev 42423)
@@ -95,6 +95,8 @@
 
 	void engine(void);
 
+	void checkSpeechFileEndianness();
+
 private:
 	uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
 	void playSample(QueueElement *elem);
@@ -116,6 +118,7 @@
 	uint8		 _endOfQueue;
 	Audio::Mixer *_mixer;
 	ResMan *_resMan;
+	bool _bigEndianSpeech;
 	char _filePath[100];
 	static const char _musicList[270];
 	static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];

Modified: scummvm/trunk/engines/sword1/sword1.cpp
===================================================================
--- scummvm/trunk/engines/sword1/sword1.cpp	2009-07-12 16:59:29 UTC (rev 42422)
+++ scummvm/trunk/engines/sword1/sword1.cpp	2009-07-12 18:52:38 UTC (rev 42423)
@@ -145,6 +145,10 @@
 
 	_systemVars.playSpeech = 1;
 	_mouseState = 0;
+	
+	// Some Mac versions use big endian for the speech files but not all of them.
+	if (_systemVars.platform == Common::kPlatformMacintosh)
+		_sound->checkSpeechFileEndianness();
 
 	_logic->initialize();
 	_objectMan->initialize();


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list