[Scummvm-cvs-logs] scummvm master -> 0d090495627453ae5d1e71f4fe11d888ab04d5fe

m-kiewitz m_kiewitz at users.sourceforge.net
Mon Jun 8 20:10:24 CEST 2015


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:
0d09049562 SHERLOCK: add music + sync to 3DO intro


Commit: 0d090495627453ae5d1e71f4fe11d888ab04d5fe
    https://github.com/scummvm/scummvm/commit/0d090495627453ae5d1e71f4fe11d888ab04d5fe
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-08T20:09:29+02:00

Commit Message:
SHERLOCK: add music + sync to 3DO intro

Changed paths:
    engines/sherlock/music.cpp
    engines/sherlock/music.h
    engines/sherlock/scalpel/scalpel.cpp



diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index c00be10..8b1f173 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -24,6 +24,8 @@
 #include "sherlock/sherlock.h"
 #include "sherlock/music.h"
 #include "sherlock/scalpel/drivers/mididriver.h"
+// for 3DO digital music
+#include "audio/decoders/aiff.h"
 
 namespace Sherlock {
 
@@ -190,16 +192,15 @@ bool MidiParser_SH::loadMusic(byte *data, uint32 size) {
 /*----------------------------------------------------------------*/
 
 Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
+	_midiDriver = NULL;
+	_midiParser = NULL;
+	_musicType = MT_NULL;
 	_musicPlaying = false;
-	_musicOn = true;
+	_musicOn = false;
 
 	if (_vm->getPlatform() == Common::kPlatform3DO) {
-		// 3DO - disable music
-		// TODO: Implement music support
-		_driver = NULL;
-		_midiParser = NULL;
-		_musicType = MT_NULL;
-		_musicOn = false;
+		// 3DO - uses digital samples for music
+		_musicOn = true;
 		return;
 	}
 
@@ -211,18 +212,16 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
 	_musicType = MidiDriver::getMusicType(dev);
 
-	_driver = NULL;
-
 	switch (_musicType) {
 	case MT_ADLIB:
-		_driver = MidiDriver_AdLib_create();
+		_midiDriver = MidiDriver_AdLib_create();
 		break;
 	case MT_MT32:
-		_driver = MidiDriver_MT32_create();
+		_midiDriver = MidiDriver_MT32_create();
 		break;
 	case MT_GM:
 		if (ConfMan.getBool("native_mt32")) {
-			_driver = MidiDriver_MT32_create();
+			_midiDriver = MidiDriver_MT32_create();
 			_musicType = MT_MT32;
 		}
 		break;
@@ -233,16 +232,14 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
 		break;
 	}
 
-	if (_driver) {
-		assert(_driver);
-
-		int ret = _driver->open();
+	if (_midiDriver) {
+		int ret = _midiDriver->open();
 		if (ret == 0) {
 			// Reset is done inside our MIDI driver
-			_driver->setTimerCallback(_midiParser, &_midiParser->timerCallback);
+			_midiDriver->setTimerCallback(_midiParser, &_midiParser->timerCallback);
 		}
-		_midiParser->setMidiDriver(_driver);
-		_midiParser->setTimerRate(_driver->getBaseTempo());
+		_midiParser->setMidiDriver(_midiDriver);
+		_midiParser->setTimerRate(_midiDriver->getBaseTempo());
 
 		if (_musicType == MT_MT32) {
 			// Upload patches
@@ -259,12 +256,11 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
 			byte *MT32driverDataPtr = MT32driverData + 12;
 			MT32driverDataSize -= 12;
 
-			MidiDriver_MT32_uploadPatches(_driver, MT32driverDataPtr, MT32driverDataSize);
+			MidiDriver_MT32_uploadPatches(_midiDriver, MT32driverDataPtr, MT32driverDataSize);
 			delete[] MT32driverData;
 		}
-	} else {
-		// no driver, bye bye music
-		_musicOn = false;
+
+		_musicOn = true;
 	}
 }
 
@@ -274,9 +270,9 @@ Music::~Music() {
 		_midiParser->stopPlaying();
 		delete _midiParser;
 	}
-	if (_driver) {
-		_driver->close();
-		delete _driver;
+	if (_midiDriver) {
+		_midiDriver->close();
+		delete _midiDriver;
 	}
 }
 
@@ -321,66 +317,92 @@ void Music::syncMusicSettings() {
 }
 
 bool Music::playMusic(const Common::String &name) {
-	if (!_driver)
-		return false;
 	if (!_musicOn)
 		return false;
 
 	debugC(kDebugLevelMusic, "Music: playMusic('%s')", name.c_str());
-	Common::SeekableReadStream *stream = _vm->_res->load(name, "MUSIC.LIB");
 
-	byte *data = new byte[stream->size()];
-	int32 dataSize = stream->size();
-	assert(data);
+	if (_vm->getPlatform() != Common::kPlatform3DO) {
+		// MIDI based
+		if (!_midiDriver)
+			return false;
+
+		Common::SeekableReadStream *stream = _vm->_res->load(name, "MUSIC.LIB");
 
-	stream->read(data, dataSize);
-	delete stream;
+		byte *data = new byte[stream->size()];
+		int32 dataSize = stream->size();
+		assert(data);
 
-	// for dumping the music tracks
+		stream->read(data, dataSize);
+		delete stream;
+
+		// for dumping the music tracks
 #if 0
-	Common::DumpFile outFile;
-	outFile.open(name + ".RAW");
-	outFile.write(data, stream->size());
-	outFile.flush();
-	outFile.close();
+		Common::DumpFile outFile;
+		outFile.open(name + ".RAW");
+		outFile.write(data, stream->size());
+		outFile.flush();
+		outFile.close();
 #endif
 
-	if (dataSize < 14) {
-		warning("Music: not enough data in music file");
-		return false;
-	}
+		if (dataSize < 14) {
+			warning("Music: not enough data in music file");
+			return false;
+		}
 
-	byte *dataPos = data;
-	if (memcmp("            ", dataPos, 12)) {
-		warning("Music: expected header not found in music file");
-		return false;
-	}
-	dataPos += 12;
-	dataSize -= 12;
+		byte *dataPos = data;
+		if (memcmp("            ", dataPos, 12)) {
+			warning("Music: expected header not found in music file");
+			return false;
+		}
+		dataPos += 12;
+		dataSize -= 12;
 
-	uint16 headerSize = READ_LE_UINT16(dataPos);
-	if (headerSize != 0x7F) {
-		warning("Music: header is not as expected");
-		return false;
-	}
+		uint16 headerSize = READ_LE_UINT16(dataPos);
+		if (headerSize != 0x7F) {
+			warning("Music: header is not as expected");
+			return false;
+		}
 
-	if (_driver) {
 		switch (_musicType) {
 		case MT_ADLIB:
-			MidiDriver_AdLib_newMusicData(_driver, dataPos, dataSize);
+			MidiDriver_AdLib_newMusicData(_midiDriver, dataPos, dataSize);
 			break;
 
 		case MT_MT32:
-			MidiDriver_MT32_newMusicData(_driver, dataPos, dataSize);
+			MidiDriver_MT32_newMusicData(_midiDriver, dataPos, dataSize);
 			break;
 
 		default:
 			// should never happen
 			break;
 		}
-	}
 
-	_midiParser->loadMusic(dataPos, dataSize);
+		_midiParser->loadMusic(dataPos, dataSize);
+
+	} else {
+		// 3DO: sample based
+		Audio::AudioStream *musicStream;
+		Common::String digitalMusicName = "music/" + name + "_MW22.aifc";
+
+		if (isPlaying()) {
+			_mixer->stopHandle(_digitalMusicHandle);
+		}
+
+		Common::File *digitalMusicFile = new Common::File();
+		if (!digitalMusicFile->open(digitalMusicName)) {
+			warning("playMusic: can not open 3DO music '%s'", digitalMusicName.c_str());
+			return false;
+		}
+
+		// Try to load the given file as AIFF/AIFC
+		musicStream = Audio::makeAIFFStream(digitalMusicFile, DisposeAfterUse::YES);
+		if (!musicStream) {
+			warning("playMusic: can not load 3DO music '%s'", digitalMusicName.c_str());
+			return false;
+		}
+		_mixer->playStream(Audio::Mixer::kMusicSoundType, &_digitalMusicHandle, musicStream);
+	}
 	return true;
 }
 
@@ -388,6 +410,15 @@ void Music::stopMusic() {
 	// TODO
 	warning("TODO: Sound::stopMusic");
 
+	if (_vm->getPlatform() != Common::kPlatform3DO) {
+		// TODO
+	} else {
+		// 3DO
+		if (isPlaying()) {
+			_mixer->stopHandle(_digitalMusicHandle);
+		}
+	}
+
 	_musicPlaying = false;
 }
 
@@ -410,6 +441,27 @@ void Music::waitTimerRoland(uint time) {
 	warning("TODO: Sound::waitTimerRoland");
 }
 
+bool Music::isPlaying() {
+	if (_vm->getPlatform() != Common::kPlatform3DO) {
+		// MIDI based
+		return _midiParser->isPlaying();
+	} else {
+		// 3DO: sample based
+		return _mixer->isSoundHandleActive(_digitalMusicHandle);
+	}
+}
+
+// Returns the current music position in milliseconds
+uint32 Music::getCurrentPosition() {
+	if (_vm->getPlatform() != Common::kPlatform3DO) {
+		// MIDI based
+		return (_midiParser->getTick() * 1000) / 60; // translate tick to millisecond
+	} else {
+		// 3DO: sample based
+		return _mixer->getSoundElapsedTime(_digitalMusicHandle);
+	}
+}
+
 // This is used to wait for the music in certain situations like especially the intro
 // Note: the original game didn't do this, instead it just waited for certain amounts of time
 //       We do this, so that the intro graphics + music work together even on faster/slower hardware.
@@ -445,5 +497,39 @@ bool Music::waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, u
 	}
 }
 
-} // End of namespace Sherlock
+// This is used to wait for the music in certain situations like especially the intro
+// Note: the original game didn't do this, instead it just waited for certain amounts of time
+//       We do this, so that the intro graphics + music work together even on faster/slower hardware.
+bool Music::waitUntilMSec(uint32 msecTarget, uint32 msecMax, uint32 additionalDelay, uint32 noMusicDelay) {
+	uint32 msecCurrent = 0;
+
+	if (!isPlaying()) {
+		return _vm->_events->delay(noMusicDelay, true);
+	}
+	while (1) {
+		if (!isPlaying()) { // Music is not playing anymore -> we are done
+			if (additionalDelay > 0) {
+				if (!_vm->_events->delay(additionalDelay, true))
+					return false;
+			}
+			return true;
+		}
+
+		msecCurrent = getCurrentPosition();
+		//warning("waitUntilMSec: %lx", msecCurrent);
+
+		if ((!msecMax) || (msecCurrent <= msecMax)) {
+			if (msecCurrent >= msecTarget) {
+				if (additionalDelay > 0) {
+					if (!_vm->_events->delay(additionalDelay, true))
+						return false;
+				}
+				return true;
+			}
+		}
+		if (!_vm->_events->delay(10, true))
+			return false;
+	}
+}
 
+} // End of namespace Sherlock
diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h
index b11a769..f8cad3f 100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@ -27,6 +27,9 @@
 #include "audio/midiparser.h"
 //#include "audio/mididrv.h"
 #include "sherlock/scalpel/drivers/mididriver.h"
+// for 3DO digital music
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
 
 namespace Sherlock {
 
@@ -58,7 +61,8 @@ private:
 	SherlockEngine *_vm;
 	Audio::Mixer *_mixer;
 	MidiParser_SH *_midiParser;
-	MidiDriver *_driver;
+	MidiDriver *_midiDriver;
+	Audio::SoundHandle _digitalMusicHandle;
 
 public:
 	bool _musicPlaying;
@@ -105,7 +109,12 @@ public:
 	
 	void waitTimerRoland(uint time);
 
+	bool isPlaying();
+	uint32 getCurrentPosition();
+
 	bool waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, uint32 noMusicDelay);
+
+	bool waitUntilMSec(uint32 msecTarget, uint32 maxMSec, uint32 additionalDelay, uint32 noMusicDelay);
 };
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index bf961dd..af06f45 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -531,6 +531,12 @@ bool ScalpelEngine::showOfficeCutscene() {
 bool ScalpelEngine::showCityCutscene3DO() {
 	_animation->_soundLibraryFilename = "TITLE.SND";
 
+	// Play intro music
+	_music->playMusic("prolog");
+
+	// rain.aiff seems to be playing in an endless loop until
+	// sherlock logo fades away TODO
+
 	bool finished = _animation->play3DO("26open1", true, 1, 255, 2);
 
 	if (finished) {
@@ -548,8 +554,8 @@ bool ScalpelEngine::showCityCutscene3DO() {
 			ImageFile3DO titleImage_November("title2b.cel");
 
 			_screen->transBlitFromUnscaled3DO(titleImage_November[0]._frame, Common::Point(101, 100));
-			finished = _events->delay(5000, true);
 
+			finished = _music->waitUntilMSec(14700, 0, 0, 5000);
 		}
 
 		if (finished) {
@@ -562,8 +568,6 @@ bool ScalpelEngine::showCityCutscene3DO() {
 		finished = _animation->play3DO("26open2", true, 1, 0, 2);
 
 	if (finished) {
-		_screen->_backBuffer2.blitFrom(*_screen);
-
 		// "Sherlock Holmes" (title)
 		ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel");
 
@@ -578,14 +582,10 @@ bool ScalpelEngine::showCityCutscene3DO() {
 			finished = _events->delay(3500, true);
 		}
 		// Title is supposed to get faded away after that
-		if (finished) {
-			// Restore screen
-			_screen->blitFrom(_screen->_backBuffer2);
-		}
 	}
 
 	if (finished)
-		finished = _events->delay(2000);
+		finished = _music->waitUntilMSec(33600, 0, 0, 2000);
 
 	if (finished) {
 		// TODO: fade to black
@@ -598,44 +598,56 @@ bool ScalpelEngine::showCityCutscene3DO() {
 
 		_screen->transBlitFromUnscaled3DO(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
 		// TODO: Supposed to get faded in and out
-		finished = _events->delay(2500, true);
+		finished = _music->waitUntilMSec(39900, 0, 0, 2500);
 
 		// Fade out
+		_screen->clear();
 	}
 	return finished;
 }
 
 bool ScalpelEngine::showAlleyCutscene3DO() {
-	bool finished = _animation->play3DO("27PRO1", true, 1, 3, 2);
+	bool finished = _music->waitUntilMSec(44000, 0, 0, 1000);
+
+	if (finished)
+		finished = _animation->play3DO("27PRO1", true, 1, 3, 2);
 
 	if (finished) {
 		// Fade out...
 		_screen->clear();
 
-		finished = _events->delay(1000, true);
+		finished = _music->waitUntilMSec(66700, 0, 0, 1000);
 	}
 
 	if (finished)
 		finished = _animation->play3DO("27PRO2", true, 1, 0, 2);
 
 	if (finished) {
+		// Fade out
+		_screen->clear();
+
+		finished = _music->waitUntilMSec(76000, 0, 0, 1000);
+	}
+
+	if (finished) {
 		// Show screaming victim
 		ImageFile3DO titleImage_ScreamingVictim("scream.cel");
 
+		_screen->clear();
 		_screen->transBlitFromUnscaled3DO(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
 
 		// Play "scream.aiff"
 		if (_sound->_voices)
 			_sound->playSound("prologue/sounds/scream.aiff", WAIT_RETURN_IMMEDIATELY, 100);
 
-		finished = _events->delay(6000, true);
+		finished = _music->waitUntilMSec(81600, 0, 0, 6000);
 	}
 
 	if (finished) {
 		// TODO: quick fade out
 		_screen->clear();
 
-		finished = _events->delay(2000, true);
+		finished = _music->waitUntilMSec(84400, 0, 0, 2000);
 	}
 
 	if (finished)
@@ -653,22 +665,21 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
 		_screen->transBlitFromUnscaled3DO(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
 		// TODO: Fade in
 
-		finished = _events->delay(3000, true);
+		finished = _music->waitUntilMSec(96700, 0, 0, 3000);
 	}
 
 	return finished;
 }
 
 bool ScalpelEngine::showStreetCutscene3DO() {
-	// wait a bit
-	bool finished = _events->delay(500);
+	bool finished = true;
 
 	if (finished) {
 		// fade out "Early the following morning..."
 		_screen->clear();
 
 		// wait for music a bit
-		finished = _events->delay(1000, true);
+		finished = _music->waitUntilMSec(100300, 0, 0, 1000);
 	}
 
 	finished = _animation->play3DO("14KICK", true, 1, 3, 2);
@@ -677,16 +688,25 @@ bool ScalpelEngine::showStreetCutscene3DO() {
 		finished = _animation->play3DO("14NOTE", true, 1, 0, 3);
 
 	// TODO: fade out
+	_screen->clear();
 
 	return finished;
 }
 
 bool ScalpelEngine::showOfficeCutscene3DO() {
-	bool finished = _animation->play3DO("COFF1", true, 1, 3, 3);
+	bool finished = true;
+
+	finished = _music->waitUntilMSec(151000, 0, 0, 1000);
+
+	if (finished)
+		_animation->play3DO("COFF1", true, 1, 3, 3);
 
 	if (finished)
 		finished = _animation->play3DO("COFF2", true, 1, 0, 3);
 
+	if (finished)
+		finished = _music->waitUntilMSec(182400, 0, 0, 1000);
+
 	if (finished) {
 		// Show the note
 		ImageFile3DO titleImage_CoffeeNote("note.cel");
@@ -699,13 +719,17 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
 		} else
 			finished = _events->delay(19000);
 
-		if (finished) {
-			_events->clearEvents();
-			finished = _events->delay(500);
-		}
+		if (finished)
+			finished = _music->waitUntilMSec(218800, 0, 0, 1000);
+
+		// Fade out
+		_screen->clear();
 	}
 
 	if (finished)
+		finished = _music->waitUntilMSec(222200, 0, 0, 1000);
+
+	if (finished)
 		finished = _animation->play3DO("COFF3", true, 1, 0, 3);
 
 	if (finished)






More information about the Scummvm-git-logs mailing list