[Scummvm-cvs-logs] SF.net SVN: scummvm:[40904] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Tue May 26 12:02:25 CEST 2009


Revision: 40904
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40904&view=rev
Author:   thebluegr
Date:     2009-05-26 10:02:25 +0000 (Tue, 26 May 2009)

Log Message:
-----------
Rewrote the Audio stream parser. The introduction of KQ6 should work more correctly now (apart from Cassima's speech)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/ksound.cpp
    scummvm/trunk/engines/sci/resource.cpp
    scummvm/trunk/engines/sci/resource.h

Modified: scummvm/trunk/engines/sci/engine/ksound.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/ksound.cpp	2009-05-26 09:35:53 UTC (rev 40903)
+++ scummvm/trunk/engines/sci/engine/ksound.cpp	2009-05-26 10:02:25 UTC (rev 40904)
@@ -1001,37 +1001,18 @@
 	int sampleLen = 0;
 
 	if (!s->sound.audioResource)
-		s->sound.audioResource = new AudioResource();
+		s->sound.audioResource = new AudioResource(s->resmgr, s->version);
 
 	switch (UKPV(0)) {
 	case kSci1AudioWPlay:
 	case kSci1AudioPlay: {
 		s->sound.audioResource->stop();
 
-		Audio::AudioStream *audioStream = 0;
+		Audio::AudioStream *audioStream = 
+			audioStream = s->sound.audioResource->getAudioStream(UKPV(1), &sampleLen);
 
-		// Try to load from an external patch file first
-		Sci::Resource* audioRes = s->resmgr->findResource(kResourceTypeAudio, UKPV(1), 1);
-
-		if (s->_gameName == "KQ5") {
-			if (audioRes) {
-				audioStream = s->sound.audioResource->getAudioStreamKQ5CD(audioRes, &sampleLen);
-			} else {
-				// No patch file found, read it from the audio volume
-				audioStream = s->sound.audioResource->getAudioStreamKQ5CD(UKPV(1), &sampleLen);
-			}
-		} else if (s->_gameName == "Kq6") {
-			if (audioRes) {
-				audioStream = s->sound.audioResource->getAudioStreamKQ6Floppy(audioRes, &sampleLen);
-			} else {
-				// No patch file found, read it from the audio volume
-				audioStream = s->sound.audioResource->getAudioStreamKQ6Floppy(UKPV(1), &sampleLen);
-			}
-		}
-
 		if (audioStream)
 			mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->sound.audioResource->getAudioHandle(), audioStream);
-
 		}
 		return make_reg(0, sampleLen);		// return sample length in ticks
 	case kSci1AudioStop:

Modified: scummvm/trunk/engines/sci/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource.cpp	2009-05-26 09:35:53 UTC (rev 40903)
+++ scummvm/trunk/engines/sci/resource.cpp	2009-05-26 10:02:25 UTC (rev 40904)
@@ -56,6 +56,13 @@
 
 const int sci_max_resource_nr[] = {65536, 1000, 2048, 2048, 2048, 65536, 65536, 65536};
 
+enum SolFlags {
+	kSolFlagCompressed = 1 << 0,
+	kSolFlagUnknown    = 1 << 1,
+	kSolFlag16Bit      = 1 << 2,
+	kSolFlagIsSigned   = 1 << 3
+};
+
 const char *sci_error_types[] = {
 	"No error",
 	"I/O error",
@@ -1168,19 +1175,28 @@
 }
 
 
-AudioResource::AudioResource() {
+AudioResource::AudioResource(ResourceManager *resMgr, int sciVersion) {
+	_resMgr = resMgr;
+	_sciVersion = sciVersion;
 	_audioRate = 0;
 	_lang = 0;
-	_audioMap = 0;
+	_audioMapSCI1 = 0;
+	_audioMapSCI11 = 0;
 }
 
-AudioResource::~AudioResource() { 
-	delete[] _audioMap;
-	_audioMap = 0;
+AudioResource::~AudioResource() {
+	if (_sciVersion < SCI_VERSION_1_1) {
+		if (_audioMapSCI1) {
+			delete[] _audioMapSCI1;
+			_audioMapSCI1 = 0;
+		}
+	} else {
+		_resMgr->unlockResource(_audioMapSCI11, 65535, kResourceTypeMap);
+	}
 }
 
+// Used in SCI1 games
 void AudioResource::setAudioLang(int16 lang) {
-	// TODO: CD Audio (used for example in the end credits of KQ6CD)
 	if (lang != -1) {
 		_lang = lang;
 
@@ -1190,12 +1206,12 @@
 		Common::File* audioMapFile = new Common::File();
 		if (audioMapFile->open(filename)) {
 			// The audio map is freed in the destructor
-			_audioMap = new byte[audioMapFile->size()];
-			audioMapFile->read(_audioMap, audioMapFile->size());
+			_audioMapSCI1 = new byte[audioMapFile->size()];
+			audioMapFile->read(_audioMapSCI1, audioMapFile->size());
 			audioMapFile->close();
 			delete audioMapFile;
 		} else {
-			_audioMap = 0;
+			_audioMapSCI1 = 0;
 		}
 	}
 }
@@ -1208,7 +1224,7 @@
 	}
 }
 
-bool AudioResource::findAudEntryKQ5CD(uint16 audioNumber, byte& volume, uint32& offset, uint32& size) {
+bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size) {
 	// AUDIO00X.MAP contains 10-byte entries:
 	// w nEntry
 	// dw offset+volume (as in resource.map)
@@ -1217,10 +1233,10 @@
 	uint16 n;
 	uint32 off;
 
-	if (_audioMap == 0)
+	if (_audioMapSCI1 == 0)
 		return false;
 
-	byte *ptr = _audioMap;
+	byte *ptr = _audioMapSCI1;
 	while ((n = READ_UINT16(ptr)) != 0xFFFF) {
 		if (n == audioNumber) {
 			off = READ_LE_UINT32(ptr + 2);
@@ -1235,131 +1251,154 @@
 	return false;
 }
 
-Audio::AudioStream* AudioResource::getAudioStreamKQ5CD(uint16 audioNumber, int* sampleLen) {
-	Audio::AudioStream *audioStream = 0;
-	byte volume;
-	uint32 offset;
-	uint32 size;
+bool AudioResource::findAudEntrySCI11(uint16 audioNumber, uint32 &offset) {
+	// 65535.MAP contains 6-byte entries:
+	// w nEntry
+	// dw offset
+	// ending with 6 0xFFs
+	uint16 n;
+	offset = 0;
+	uint16 cur = 0;
 
-	if (findAudEntryKQ5CD(audioNumber, volume, offset, size)) {
-		uint32 start = offset * 1000 / _audioRate;
-		uint32 duration = size * 1000 / _audioRate;
+	if (!_audioMapSCI11)
+		_audioMapSCI11 = _resMgr->findResource(kResourceTypeMap, 65535, 1);
 
-		char filename[40];
-		sprintf(filename, "AUDIO%03d.%03d", _lang, volume);
+	byte *ptr = _audioMapSCI11->data;
+	while (cur < _audioMapSCI11->size) {
+		n = READ_UINT16(ptr);
+		offset = READ_UINT32(ptr + 2);
 
-		// Try to load compressed
-		audioStream = Audio::AudioStream::openStreamFile(filename, start, duration); 
-		if (!audioStream) { 
-			// Compressed file load failed, try to load original raw data
-			byte *soundbuff = (byte *)malloc(size);
-			Common::File* audioFile = new Common::File();
-			if (audioFile->open(filename)) {
-				audioFile->seek(offset);
-				audioFile->read(soundbuff, size);
-				audioFile->close();
-				delete audioFile;
+		// Check if we reached the end
+		if (n == 0xFF && offset == 0xFFFF)
+			return false;
 
-				audioStream = Audio::makeLinearInputStream(soundbuff, size,	_audioRate,
-						Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED, 0, 0);
-			}
-		}
+		if (n == audioNumber)
+			return true;
 
-		*sampleLen = size * 60 / _audioRate;
+		ptr += 6;
+		cur += 6;
 	}
 
-	return audioStream;
+	return false;
 }
 
-bool AudioResource::findAudEntryKQ6Floppy(uint16 audioNumber, uint32& offset) {
-	// 65535.MAP contains 8-byte entries:
-	// w nEntry
-	// dw offset
-	// w unknown
-	uint16 n;
-	offset = 0;
-	int cur = 0;
-	int fileSize = 0;
+// Sierra SOL audio file reader
+// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
+// TODO: improve this for later versions of the format, as this currently only reads
+// raw PCM encoded files (not ADPCM compressed ones)
+byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 *audioRate, byte *flags) {
+	byte audioFlags;
+	byte version = audioStream->readByte();
 
-	// Load audio map
-	Common::File* audioMapFile = new Common::File();
-	if (audioMapFile->open("65535.map")) {
-		_audioMap = new byte[audioMapFile->size()];
-		audioMapFile->read(_audioMap, audioMapFile->size());
-		fileSize = audioMapFile->size();
-		audioMapFile->close();
-		delete audioMapFile;
-	} else {
-		_audioMap = 0;
-		return false;
+	if (version != 0x8D) {
+		warning("SOL audio version is newer than the expected one");
+		return NULL;
 	}
 
-	byte *ptr = _audioMap;
-	while (cur < fileSize) {
-		n = READ_UINT16(ptr);
-		if (n == audioNumber) {
-			offset = READ_LE_UINT32(ptr + 2);
-			delete[] _audioMap;
-			_audioMap = 0;
-			return true;
-		}
-		ptr += 8;
-		cur += 8;
+	audioStream->readByte();				// skip header size (1 byte), usually 0B (11 bytes)
+	audioStream->readUint32LE();			// skip "SOL" + 0 (4 bytes)
+	*audioRate = audioStream->readUint16LE();
+	audioFlags = audioStream->readByte();
+
+	if (audioFlags & kSolFlagCompressed) {
+		warning("ADPCM compressed SOL files are not supported yet");
+		return NULL;
 	}
 
-	delete[] _audioMap;
-	_audioMap = 0;
-	return false;
+	// Convert the SOL stream flags to our own format
+	*flags = 0;
+	if (audioFlags & kSolFlag16Bit)
+		*flags |= Audio::Mixer::FLAG_16BITS;
+	if (!(audioFlags & kSolFlagIsSigned))
+		*flags |= Audio::Mixer::FLAG_UNSIGNED;
+
+	*size = audioStream->readUint16LE();
+
+	// We assume that the sound data is raw PCM
+	byte *buffer = new byte[*size];
+	audioStream->read(buffer, *size);
+	return buffer;
 }
 
-Audio::AudioStream* AudioResource::getAudioStreamKQ6Floppy(uint16 audioNumber, int* sampleLen) {
+Audio::AudioStream* AudioResource::getAudioStream(uint16 audioNumber, int *sampleLen) {
 	Audio::AudioStream *audioStream = 0;
+	byte volume;
 	uint32 offset;
 	uint32 size;
+	bool found = false;
+	byte *data = 0;
+	char filename[40];
+	byte flags;
 
-	if (findAudEntryKQ6Floppy(audioNumber, offset)) {
-		Common::File* audioFile = new Common::File();
-		if (audioFile->open("resource.aud")) {
-			audioFile->seek(offset);
-			// Read audio file info
-			// Audio files are actually Sierra Audio files.
-			// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
-			audioFile->readByte();			// skip version
-			audioFile->readByte();			// skip header size
-			audioFile->readUint32LE();		// skip "SOL" + 0
-			_audioRate = audioFile->readUint16LE();
-			audioFile->readByte();			// skip flags
-			size = audioFile->readUint16LE();
-			byte *soundbuff = (byte *)malloc(size);
-			audioFile->read(soundbuff, size); 
-			audioFile->close();
-			delete audioFile;
+	// Try to load from an external patch file first
+	Sci::Resource* audioRes = _resMgr->findResource(kResourceTypeAudio, audioNumber, 1);
+	if (audioRes) {
+		if (_sciVersion < SCI_VERSION_1_1) {
+			size = audioRes->size;
+			data = audioRes->data;
+		} else {
+			// TODO: this is disabled for now, as for some reason the resource manager returns
+			// only the data chunk of the audio file, and not its headers
+			/*
+			Common::MemoryReadStream *memStream = 
+				new Common::MemoryReadStream(audioRes->data, audioRes->size, true);
+			data = readSOLAudio(memStream, &size, &_audioRate, &flags);
+			delete memStream;
+			*/
+		}
 
-			audioStream = Audio::makeLinearInputStream(soundbuff, size,	_audioRate,
-				Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED, 0, 0);
+		if (data) {
+			*sampleLen = size * 60 / _audioRate;
+			return Audio::makeLinearInputStream(data, size, _audioRate, 
+											flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
 		}
+	}
 
-		*sampleLen = size * 60 / _audioRate;
+	// Patch file not found, load it from the audio file
+	if (_sciVersion < SCI_VERSION_1_1) {
+		found = findAudEntrySCI1(audioNumber, volume, offset, size);
+		sprintf(filename, "AUDIO%03d.%03d", _lang, volume);
+	} else {
+		found = findAudEntrySCI11(audioNumber, offset);
+		strcpy(filename, "RESOURCE.AUD");
 	}
 
-	return audioStream;
-}
+	if (found) {
+		if (_sciVersion < SCI_VERSION_1_1) {
+			uint32 start = offset * 1000 / _audioRate;
+			uint32 duration = size * 1000 / _audioRate;
+		
+			// Try to load compressed
+			audioStream = Audio::AudioStream::openStreamFile(filename, start, duration); 
+		}
 
-Audio::AudioStream* AudioResource::getAudioStreamKQ5CD(Resource* audioRes, int* sampleLen) {
-	*sampleLen = audioRes->size * 60 / _audioRate;
-	return Audio::makeLinearInputStream(audioRes->data, audioRes->size, _audioRate, Audio::Mixer::FLAG_UNSIGNED, 0, 0);
-}
+		if (!audioStream) { 
+			// Compressed file load failed, try to load original raw data
+			Common::File* audioFile = new Common::File();
+			if (audioFile->open(filename)) {
+				audioFile->seek(offset);
 
-Audio::AudioStream* AudioResource::getAudioStreamKQ6Floppy(Resource* audioRes, int* sampleLen) {
-	// Read audio file info
-	// Audio files are actually Sierra Audio files.
-	// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
-	_audioRate = READ_UINT16(audioRes->data + 6);
-	uint32 size = READ_UINT16(audioRes->data + 9);
+				if (_sciVersion < SCI_VERSION_1_1) {
+					data = (byte *)malloc(size);
+					audioFile->read(data, size);
+				} else {
+					data = readSOLAudio(audioFile, &size, &_audioRate, &flags);
+				}
 
-	*sampleLen = size * 60 / _audioRate;
-	return Audio::makeLinearInputStream(audioRes->data + 11, size, _audioRate, Audio::Mixer::FLAG_UNSIGNED, 0, 0);
+				audioFile->close();
+				delete audioFile;
+
+				if (data) {
+					audioStream = Audio::makeLinearInputStream(data, size, _audioRate,
+													flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
+				}
+			}
+		}
+
+		*sampleLen = size * 60 / _audioRate;
+	}
+
+	return audioStream;
 }
 
-
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2009-05-26 09:35:53 UTC (rev 40903)
+++ scummvm/trunk/engines/sci/resource.h	2009-05-26 10:02:25 UTC (rev 40904)
@@ -304,7 +304,7 @@
 
 class AudioResource {
 public:
-	AudioResource();
+	AudioResource(ResourceManager *resMgr, int sciVersion);
 	~AudioResource();
 
 	void setAudioRate(uint16 audioRate) { _audioRate = audioRate; }
@@ -313,11 +313,7 @@
 	Audio::SoundHandle* getAudioHandle() { return &_audioHandle; }
 	int getAudioPosition();
 
-	// TODO: these need better names
-	Audio::AudioStream* getAudioStreamKQ5CD(uint16 audioNumber, int* sampleLen);
-	Audio::AudioStream* getAudioStreamKQ5CD(Resource* audioRes, int* sampleLen);
-	Audio::AudioStream* getAudioStreamKQ6Floppy(uint16 audioNumber, int* sampleLen);
-	Audio::AudioStream* getAudioStreamKQ6Floppy(Resource* audioRes, int* sampleLen);
+	Audio::AudioStream* getAudioStream(uint16 audioNumber, int *sampleLen);
 
 	void stop() { g_system->getMixer()->stopHandle(_audioHandle); }
 	void pause() { g_system->getMixer()->pauseHandle(_audioHandle, true); }
@@ -327,11 +323,13 @@
 	Audio::SoundHandle _audioHandle;
 	uint16 _audioRate;
 	int16 _lang;
-	byte *_audioMap;
+	byte *_audioMapSCI1;
+	Resource *_audioMapSCI11;
+	ResourceManager *_resMgr;
+	int _sciVersion;
 
-	// TODO: these need better names
-	bool findAudEntryKQ5CD(uint16 audioNumber, byte& volume, uint32& offset, uint32& size);
-	bool findAudEntryKQ6Floppy(uint16 audioNumber, uint32& offset);
+	bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size);
+	bool findAudEntrySCI11(uint16 audioNumber, uint32 &offset);
 };
 
 } // End of namespace Sci


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