[Scummvm-cvs-logs] scummvm master -> acc7cd58a203fb0c1991c3b8b35c2f296b739f06

dreammaster dreammaster at scummvm.org
Tue Oct 15 04:59:04 CEST 2013


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
acc7cd58a2 TSAGE: Beginnings of R2R voice streaming


Commit: acc7cd58a203fb0c1991c3b8b35c2f296b739f06
    https://github.com/scummvm/scummvm/commit/acc7cd58a203fb0c1991c3b8b35c2f296b739f06
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2013-10-14T19:58:29-07:00

Commit Message:
TSAGE: Beginnings of R2R voice streaming

Changed paths:
    engines/tsage/ringworld2/ringworld2_logic.cpp
    engines/tsage/ringworld2/ringworld2_scenes0.cpp
    engines/tsage/sound.cpp
    engines/tsage/sound.h



diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index bd90850..90df72a 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -596,6 +596,9 @@ void SceneExt::loadBlankScene() {
 
 void SceneHandlerExt::postInit(SceneObjectList *OwnerList) {
 	SceneHandler::postInit(OwnerList);
+
+	if (!R2_GLOBALS._playStream.setFile("SND4K.RES"))
+		warning("Could not find SND4K.RES voice file");
 }
 
 void SceneHandlerExt::process(Event &event) {
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index bdac160..5e4b4e4 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -836,7 +836,7 @@ void Scene125::process(Event &event) {
 
 void Scene125::dispatch() {
 	if (_soundCount)
-		R2_GLOBALS._playStream.proc1();
+		R2_GLOBALS._playStream.dispatch();
 
 	Scene::dispatch();
 }
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index b9567ce..a5480fe 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -1540,6 +1540,23 @@ void Sound::play(int soundNum) {
 	_soundManager->addToPlayList(this);
 }
 
+bool Sound::playBuffers(const byte *soundData) {
+	prime(-2);
+	_soundManager->addToPlayList(this);
+	
+	debug(1, "TODO: Sound::checkCannels");
+	if (/* _soundManager.checkChannels() */ true) {
+		uint32 size = READ_UINT32(soundData + 4);
+		if (size == 0 || size > 0xffff)
+			error("Sound::playBuffers() called with illegal buffer length");
+
+		warning("TODO: Implement Sound::primeSoundData for voice playback");
+	} else {
+		stop();
+		return false;
+	}
+}
+
 void Sound::stop() {
 	g_globals->_soundManager.removeFromPlayList(this);
 	_unPrime();
@@ -2505,6 +2522,192 @@ void ASoundExt::changeSound(int soundNum) {
 
 /*--------------------------------------------------------------------------*/
 
+void PlayStream::ResFileData::load(Common::SeekableReadStream &stream) {
+	// Validate that it's the correct data file
+	char header[4];
+	stream.read(&header[0], 4);
+	if (strncmp(header, "SPAM", 4))
+		error("Invalid voice resource data");
+
+	_fileChunkSize = stream.readUint32LE();
+	_field8 = stream.readUint16LE();
+	_indexSize = stream.readUint16LE();
+	_chunkSize = stream.readUint16LE();
+
+	stream.skip(20);
+}
+
+PlayStream::PlayStream(): EventHandler() {
+	_index = NULL;
+	_chunks[0] = _chunks[1] = NULL;
+	_voiceNum = 0;
+	_currentChunkIndex = 0;
+	_nextChunkIndex = 0;
+	_endAction = NULL;
+	_field2F0 = _field2FA = 0;
+}
+
+PlayStream::~PlayStream() {
+	remove();
+}
+
+bool PlayStream::setFile(const Common::String &filename) {
+	remove();
+
+	// Open the resource file for access
+	if (!_file.open(filename))
+		return false;
+
+	// Load header
+	_resData.load(_file);
+	
+	// Load the index
+	_index = new uint16[_resData._indexSize / 2];
+	for (uint i = 0; i < (_resData._indexSize / 2); ++i)
+		_index[i] = _file.readUint16LE();
+
+	// Allocate space for loading voice chunks into
+	_chunks[0] = new byte[_resData._chunkSize];
+	_chunks[1] = new byte[_resData._chunkSize];
+
+	// Initialise variables
+	_voiceNum = 0;
+	_currentChunkIndex = _nextChunkIndex = 0;
+
+	return true;
+}
+
+bool PlayStream::play(int voiceNum, EventHandler *endAction) {
+	uint32 offset = getFileOffset(_index, _resData._fileChunkSize, voiceNum);
+	if (offset) {
+		_voiceNum = 0;
+		_currentChunkIndex = _nextChunkIndex = 0;
+		if (_sound.isPlaying())
+			_sound.stop();
+
+		_file.seek(offset);
+		_file.read(_chunks[0], _resData._chunkSize); 
+		_file.read(_chunks[1], _resData._chunkSize);
+		
+		_currentChunkIndex = 0;
+		_nextChunkIndex = 1;
+		_voiceNum = voiceNum;
+		_endAction = endAction;
+
+		if (!strncmp((const char *)_chunks[_currentChunkIndex], "FEED", 4)) {
+			// Valid sound data found
+			const byte *data = _chunks[_currentChunkIndex];
+
+			_field2F0 = _field2FA = READ_UINT16(data + 10);
+			
+			//_fnP = proc2;
+			_field300 = this;
+			_soundData = data + 16;
+			_streamSize = READ_LE_UINT16(data + 4) - 16;
+
+			// Start playing the sound data
+			if (!_sound.playBuffers(_soundData)) {
+				_voiceNum = 0;
+				_currentChunkIndex = _nextChunkIndex = 0;
+			}
+
+			return true;
+		}
+	}
+	 
+	// If it reaches this point, no valid voice data found
+	return false;
+}
+
+void PlayStream::stop() {
+	_voiceNum = 0;
+	_currentChunkIndex = _nextChunkIndex = 0;
+	_endAction = NULL;
+
+	if (_sound.isPlaying())
+		_sound.stop();
+}
+
+bool PlayStream::isPlaying() const {
+	return _voiceNum != 0;
+}
+
+void PlayStream::remove() {
+	stop();
+	_file.close();
+
+	// Free data buffers
+	delete[] _index;
+	delete[] _chunks[0];
+	delete[] _chunks[1];
+	_index = NULL;
+	_chunks[0] = _chunks[1] = NULL;
+
+	_endAction = NULL;
+	_voiceNum = 0;
+	_currentChunkIndex = 0;
+	_nextChunkIndex = 0;
+}
+
+void PlayStream::dispatch() {
+	if ((_voiceNum != 0) && (_currentChunkIndex == _nextChunkIndex)) {
+		if (READ_LE_UINT16(_chunks[_currentChunkIndex] + 6) != 0) {
+			uint32 bytesRead = _file.read(_chunks[_nextChunkIndex ^ 1], _resData._chunkSize);
+			
+			if (bytesRead != _resData._chunkSize) {
+				byte *data = _chunks[_currentChunkIndex];
+				Common::fill(data, data + 128, 0);
+				
+				_voiceNum = 0;
+			}
+
+			_nextChunkIndex ^= 1;
+		} else if (!isPlaying()) {
+			// If voice has finished playing, reset fields
+			EventHandler *endAction = _endAction;
+			_endAction = NULL;
+			_voiceNum = 0;
+			_currentChunkIndex = 0;
+			_nextChunkIndex = 0;
+
+			if (endAction)
+				// Signal given end action
+				endAction->signal();
+		}
+	}
+}
+
+uint32 PlayStream::getFileOffset(const uint16 *data, int count, int voiceNum) {
+	assert(data);
+	int bitsIndex = voiceNum & 7;
+	int byteIndex = voiceNum >> 3;
+	int shiftAmount = bitsIndex * 2;
+	int bitMask = 3 << shiftAmount;
+	int v = (data[byteIndex] & bitMask) >> shiftAmount; 
+	uint32 offset = 0;
+
+	if (!v)
+		return 0;
+
+	// Loop to figure out offsets from indexes skipped over
+	for (int i = 0; i < (voiceNum >> 3); ++i) {
+		for (int bit = 0; bit < 16; bit += 2)
+			offset += ((data[i] >> bit) & 3) * count;
+	}
+
+	// Bit index loop
+	for (int i = 0; i < bitsIndex; --i)
+		offset += ((data[byteIndex] >> (i * 2)) & 3) * count;
+
+	return offset;
+}
+
+void PlayStream::stream() {
+	// TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
 SoundDriver::SoundDriver() {
 	_driverResID = 0;
 	_minVersion = _maxVersion = 0;
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 2f59afb..9779f3c 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -259,6 +259,7 @@ public:
 class Sound: public EventHandler {
 private:
 	void _prime(int soundResID, bool dontQueue);
+	void _primeBuffer(const byte *soundData);
 	void _unPrime();
 public:
 	bool _stoppedAsynchronously;
@@ -315,6 +316,7 @@ public:
 	void orientAfterRestore();
 
 	void play(int soundResID);
+	bool playBuffers(const byte *soundData);
 	void stop();
 	void prime(int soundResID);
 	void unPrime();
@@ -414,15 +416,46 @@ public:
 	virtual void signal();
 };
 
-class PlayStream {
-public:
+class PlayStream: public EventHandler {
+	class ResFileData {
+	public:
+		int _fileChunkSize;
+		int _field8;
+		uint _indexSize;
+		uint _chunkSize;
+
+		void load(Common::SeekableReadStream &stream);
+	};
+	typedef void (PlayStream::*FunctionPtr)();
+private:
+	Common::File _file;
+	ResFileData _resData;
 	Sound _sound;
+	uint16 *_index;
+	byte *_chunks[2];
+	const byte *_soundData;
+	int _voiceNum;
+	int _currentChunkIndex;
+	int _nextChunkIndex;
+	EventHandler *_endAction;
+	EventHandler *_field300;
+	int _field2F0, _field2FA;
+	int _streamSize;
+	FunctionPtr _streamFn;
+
+	void stream();
+	static uint32 getFileOffset(const uint16 *data, int count, int voiceNum);
+public:
+	PlayStream();
+	virtual ~PlayStream();
 
-	void setFile(const Common::String &filename) {}
-	bool play(int soundNum, EventHandler *endAction) { return false; }
-	void stop() {}
-	void proc1() {}
-	bool isPlaying() const { return false; }
+	bool setFile(const Common::String &filename); 
+	bool play(int voiceNum, EventHandler *endAction);
+	void stop();
+	bool isPlaying() const;
+
+	virtual void remove();
+	virtual void dispatch();
 };
 
 #define ADLIB_CHANNEL_COUNT 9






More information about the Scummvm-git-logs mailing list