[Scummvm-git-logs] scummvm master -> 00a1ba2ee875fb0421ab383a0148e9fdfa95d384

djsrv dservilla at gmail.com
Wed Jul 28 02:56:32 UTC 2021


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

Summary:
8a9b1cd09c DIRECTOR: Give each window its own sound manager
a2e8da00e5 DIRECTOR: Don't render next frame if exitFrame stopped the movie
a16d823201 DIRECTOR: Improve puppetSound
ff16d808c7 DIRECTOR: LINGO: Play puppet sounds in updateStage
00a1ba2ee8 DIRECTOR: Disable puppet sounds when the movie changes


Commit: 8a9b1cd09cc9ee21a1da7a1d6b62a88b84ca88cf
    https://github.com/scummvm/scummvm/commit/8a9b1cd09cc9ee21a1da7a1d6b62a88b84ca88cf
Author: djsrv (dservilla at gmail.com)
Date: 2021-07-27T22:42:09-04:00

Commit Message:
DIRECTOR: Give each window its own sound manager

This Should prevent conflicts between the sound channels of movies
running in parallel.

Changed paths:
    engines/director/director.cpp
    engines/director/director.h
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-funcs.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/xlibs/fplayxobj.cpp
    engines/director/score.cpp
    engines/director/sound.cpp
    engines/director/sound.h
    engines/director/window.cpp
    engines/director/window.h


diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index a0c49e867b..571185b788 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -68,7 +68,6 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
 	// Load key codes
 	loadKeyCodes();
 
-	_soundManager = nullptr;
 	_currentPalette = nullptr;
 	_currentPaletteLength = 0;
 	_stage = nullptr;
@@ -104,7 +103,6 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
 
 DirectorEngine::~DirectorEngine() {
 	delete _windowList;
-	delete _soundManager;
 	delete _lingo;
 	delete _wm;
 	delete _surface;
@@ -148,8 +146,6 @@ Common::Error DirectorEngine::run() {
 
 	_currentPalette = nullptr;
 
-	_soundManager = nullptr;
-
 	wmMode = debugChannelSet(-1, kDebugDesktop) ? wmModeDesktop : wmModeFullscreen;
 
 	if (debugChannelSet(-1, kDebug32bpp))
@@ -175,7 +171,6 @@ Common::Error DirectorEngine::run() {
 	_currentWindow = _stage;
 
 	_lingo = new Lingo(this);
-	_soundManager = new DirectorSound(this);
 
 	if (getGameGID() == GID_TEST) {
 		_currentWindow->runTests();
diff --git a/engines/director/director.h b/engines/director/director.h
index f73bd9c73f..432bb0b4b9 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -190,7 +190,6 @@ public:
 	const char *getExtra();
 	Common::String getEXEName() const;
 	StartMovie getStartMovie() const;
-	DirectorSound *getSoundManager() const { return _soundManager; }
 	Graphics::MacWindowManager *getMacWindowManager() const { return _wm; }
 	Archive *getMainArchive() const;
 	Lingo *getLingo() const { return _lingo; }
@@ -256,7 +255,6 @@ private:
 	const DirectorGameDescription *_gameDescription;
 	Common::FSNode _gameDataDir;
 
-	DirectorSound *_soundManager;
 	byte *_currentPalette;
 	uint16 _currentPaletteLength;
 	Lingo *_lingo;
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 666c1279ff..b62b9b89ed 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1928,7 +1928,7 @@ void LB::b_puppetSound(int nargs) {
 		return;
 	}
 
-	DirectorSound *sound = g_director->getSoundManager();
+	DirectorSound *sound = g_director->getCurrentWindow()->getSoundManager();
 	Score *score = g_director->getCurrentMovie()->getScore();
 
 	if (!score) {
@@ -2402,6 +2402,8 @@ void LB::b_sound(int nargs) {
 		return;
 	}
 
+	DirectorSound *soundManager = g_director->getCurrentWindow()->getSoundManager();
+
 	if (verb.u.s->equalsIgnoreCase("close") || verb.u.s->equalsIgnoreCase("stop")) {
 		if (nargs != 2) {
 			warning("sound %s: expected 1 argument, got %d", verb.u.s->c_str(), nargs - 1);
@@ -2409,7 +2411,7 @@ void LB::b_sound(int nargs) {
 		}
 
 		TYPECHECK(firstArg, INT);
-		g_director->getSoundManager()->stopSound(firstArg.u.i);
+		soundManager->stopSound(firstArg.u.i);
 	} else if (verb.u.s->equalsIgnoreCase("fadeIn")) {
 		if (nargs > 2) {
 			TYPECHECK(secondArg, INT);
@@ -2419,7 +2421,7 @@ void LB::b_sound(int nargs) {
 		}
 
 		TYPECHECK(firstArg, INT);
-		g_director->getSoundManager()->registerFade(firstArg.u.i, true, ticks);
+		soundManager->registerFade(firstArg.u.i, true, ticks);
 		g_director->getCurrentMovie()->getScore()->_activeFade = firstArg.u.i;
 		return;
 	} else if (verb.u.s->equalsIgnoreCase("fadeOut")) {
@@ -2431,7 +2433,7 @@ void LB::b_sound(int nargs) {
 		}
 
 		TYPECHECK(firstArg, INT);
-		g_director->getSoundManager()->registerFade(firstArg.u.i, false, ticks);
+		soundManager->registerFade(firstArg.u.i, false, ticks);
 		g_director->getCurrentMovie()->getScore()->_activeFade = firstArg.u.i;
 		return;
 	} else if (verb.u.s->equalsIgnoreCase("playFile")) {
@@ -2440,14 +2442,14 @@ void LB::b_sound(int nargs) {
 		TYPECHECK(firstArg, INT);
 		TYPECHECK(secondArg, STRING);
 
-		g_director->getSoundManager()->playFile(pathMakeRelative(*secondArg.u.s), firstArg.u.i);
+		soundManager->playFile(pathMakeRelative(*secondArg.u.s), firstArg.u.i);
 	} else {
 		warning("b_sound: unknown verb %s", verb.u.s->c_str());
 	}
 }
 
 void LB::b_soundBusy(int nargs) {
-	DirectorSound *sound = g_director->getSoundManager();
+	DirectorSound *sound = g_director->getCurrentWindow()->getSoundManager();
 	Datum whichChannel = g_lingo->pop();
 
 	TYPECHECK(whichChannel, INT);
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index 9a5b78781d..c87515f730 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -169,7 +169,7 @@ void Lingo::func_mci(const Common::String &name) {
 			uint32 from = strtol(params[1].c_str(), 0, 10);
 			uint32 to = strtol(params[2].c_str(), 0, 10);
 
-			_vm->getSoundManager()->playMCI(*_audioAliases[params[0]], from, to);
+			_vm->getCurrentWindow()->getSoundManager()->playMCI(*_audioAliases[params[0]], from, to);
 		}
 		break;
 	default:
@@ -325,7 +325,7 @@ void Lingo::func_cursor(int cursorId) {
 
 void Lingo::func_beep(int repeats) {
 	for (int r = 1; r <= repeats; r++) {
-		_vm->getSoundManager()->systemBeep();
+		_vm->getCurrentWindow()->getSoundManager()->systemBeep();
 		if (r < repeats)
 			g_system->delayMillis(400);
 	}
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 088df38f03..8462b8d9d3 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -748,14 +748,14 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		break;
 	case kTheSoundEnabled:
 		d.type = INT;
-		d.u.i = _vm->getSoundManager()->getSoundEnabled();
+		d.u.i = _vm->getCurrentWindow()->getSoundManager()->getSoundEnabled();
 		break;
 	case kTheSoundEntity:
 		{
 			switch (field) {
 			case kTheVolume:
 				{
-					SoundChannel *chan = _vm->getSoundManager()->getChannel(id.asInt());
+					SoundChannel *chan = _vm->getCurrentWindow()->getSoundManager()->getChannel(id.asInt());
 					if (chan) {
 						d.type = INT;
 						d.u.i = (int)chan->volume;
@@ -771,7 +771,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 	case kTheSoundLevel:
 		// getting sound level of channel 1, maybe need to be amended in higher version
 		d.type = INT;
-		d.u.i = _vm->getSoundManager()->getSoundLevel(1);
+		d.u.i = _vm->getCurrentWindow()->getSoundManager()->getSoundLevel(1);
 		break;
 	case kTheSprite:
 		d = getTheSprite(id, field);
@@ -1008,14 +1008,14 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		}
 		break;
 	case kTheSoundEnabled:
-		_vm->getSoundManager()->setSoundEnabled((bool)d.asInt());
+		_vm->getCurrentWindow()->getSoundManager()->setSoundEnabled((bool)d.asInt());
 		break;
 	case kTheSoundEntity:
 		{
 			switch (field) {
 			case kTheVolume:
 				{
-					SoundChannel *chan = _vm->getSoundManager()->getChannel(id.asInt());
+					SoundChannel *chan = _vm->getCurrentWindow()->getSoundManager()->getChannel(id.asInt());
 					if (chan) {
 						chan->volume = (byte)d.asInt();
 					}
@@ -1029,7 +1029,7 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 		break;
 	case kTheSoundLevel:
 		// setting all of the channel for now
-		_vm->getSoundManager()->setSouldLevel(-1, d.asInt());
+		_vm->getCurrentWindow()->getSoundManager()->setSouldLevel(-1, d.asInt());
 		break;
 	case kTheSprite:
 		setTheSprite(id, field, d);
diff --git a/engines/director/lingo/xlibs/fplayxobj.cpp b/engines/director/lingo/xlibs/fplayxobj.cpp
index 1a210e6993..fa2ddc7bc8 100644
--- a/engines/director/lingo/xlibs/fplayxobj.cpp
+++ b/engines/director/lingo/xlibs/fplayxobj.cpp
@@ -29,6 +29,7 @@
 
 #include "director/director.h"
 #include "director/sound.h"
+#include "director/window.h"
 #include "director/lingo/lingo.h"
 #include "director/lingo/xlibs/fplayxobj.h"
 
@@ -67,7 +68,7 @@ void FPlayXObj::b_fplay(int nargs) {
 		arr[i] = g_lingo->pop().asString();
 	}
 
-	DirectorSound *sound = g_director->getSoundManager();
+	DirectorSound *sound = g_director->getCurrentWindow()->getSoundManager();
 	sound->playFPlaySound(arr);
 }
 
@@ -107,7 +108,7 @@ void FPlayXObj::b_fsound(int nargs) {
 		g_lingo->dropStack(nargs);
 	}
 
-	DirectorSound *sound = g_director->getSoundManager();
+	DirectorSound *sound = g_director->getCurrentWindow()->getSoundManager();
 	if (sound->isChannelActive(1)) {
 		g_lingo->push(Datum(sound->getCurrentSound()));
 	} else {
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 530bfdfbbb..d4e78f3c7a 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -55,7 +55,7 @@ Score::Score(Movie *movie) {
 	_vm = _movie->getVM();
 	_lingo = _vm->getLingo();
 
-	_soundManager = _vm->getSoundManager();
+	_soundManager = _window->getSoundManager();
 
 	_puppetTempo = 0x00;
 	_puppetPalette = false;
@@ -707,7 +707,7 @@ void Score::playSoundChannel(uint16 frameId) {
 	Frame *frame = _frames[frameId];
 
 	debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %s Sound2 %s", frame->_sound1.asString().c_str(), frame->_sound2.asString().c_str());
-	DirectorSound *sound = _vm->getSoundManager();
+	DirectorSound *sound = _window->getSoundManager();
 
 	// puppet sound will be controlled with lingo
 	if (sound->_puppet)
@@ -738,7 +738,7 @@ void Score::playSoundChannel(uint16 frameId) {
 }
 
 void Score::playQueuedSound() {
-	DirectorSound *sound = _vm->getSoundManager();
+	DirectorSound *sound = _window->getSoundManager();
 	sound->playFPlaySound();
 }
 
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 3af480612c..8b1975429f 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -36,10 +36,11 @@
 #include "director/movie.h"
 #include "director/castmember.h"
 #include "director/sound.h"
+#include "director/window.h"
 
 namespace Director {
 
-DirectorSound::DirectorSound(DirectorEngine *vm) : _vm(vm) {
+DirectorSound::DirectorSound(Window *window) : _window(window) {
 	uint numChannels = 2;
 	if (g_director->getVersion() >= 400) {
 		numChannels = 4;
@@ -110,7 +111,7 @@ void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bo
 	if (memberID.member == 0) {
 		stopSound(soundChannel);
 	} else {
-		CastMember *soundCast = _vm->getCurrentMovie()->getCastMember(memberID);
+		CastMember *soundCast = _window->getCurrentMovie()->getCastMember(memberID);
 		if (soundCast) {
 			if (soundCast->_type != kCastSound) {
 				warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember %s", memberID.asString().c_str());
@@ -195,7 +196,7 @@ void DirectorSound::registerFade(uint8 soundChannel, bool fadeIn, int ticks) {
 	int startVol = fadeIn ? 0 :  _channels[soundChannel - 1].volume;
 	int targetVol = fadeIn ? _channels[soundChannel - 1].volume : 0;
 
-	_channels[soundChannel - 1].fade = new FadeParams(startVol, targetVol, ticks, _vm->getMacTicks(), fadeIn);
+	_channels[soundChannel - 1].fade = new FadeParams(startVol, targetVol, ticks, _window->getVM()->getMacTicks(), fadeIn);
 	_mixer->setChannelVolume(_channels[soundChannel - 1].handle, startVol);
 }
 
@@ -207,7 +208,7 @@ bool DirectorSound::fadeChannel(uint8 soundChannel) {
 	if (!fade)
 		return false;
 
-	fade->lapsedTicks = _vm->getMacTicks() - fade->startTicks;
+	fade->lapsedTicks = _window->getVM()->getMacTicks() - fade->startTicks;
 	if (fade->lapsedTicks > fade->totalTicks) {
 		cancelFade(soundChannel);
 		return false;
diff --git a/engines/director/sound.h b/engines/director/sound.h
index 37d5519d51..d714ddaaa7 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -68,7 +68,7 @@ public:
 	bool _puppet;
 
 private:
-	DirectorEngine *_vm;
+	Window *_window;
 	Common::Array<SoundChannel> _channels;
 	Audio::SoundHandle _scriptSound;
 	Audio::Mixer *_mixer;
@@ -82,7 +82,7 @@ private:
 	bool _enable;
 
 public:
-	DirectorSound(DirectorEngine *vm);
+	DirectorSound(Window *window);
 	~DirectorSound();
 
 	SoundChannel *getChannel(uint8 soundChannel);
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 2c03063478..22181a9ecd 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -36,6 +36,7 @@
 #include "director/castmember.h"
 #include "director/cursor.h"
 #include "director/channel.h"
+#include "director/sound.h"
 #include "director/sprite.h"
 #include "director/util.h"
 #include "director/sound.h"
@@ -48,6 +49,7 @@ Window::Window(int id, bool scrollable, bool resizable, bool editable, Graphics:
 	_isStage = isStage;
 	_stageColor = _wm->_colorBlack;
 	_puppetTransition = nullptr;
+	_soundManager = new DirectorSound(this);
 
 	_currentMovie = nullptr;
 	_mainArchive = nullptr;
@@ -507,7 +509,7 @@ bool Window::step() {
 		} else {
 			delete sharedCast;
 		}
-		g_director->getSoundManager()->changingMovie();
+		_soundManager->changingMovie();
 
 		_nextMovie.movie.clear();
 	}
diff --git a/engines/director/window.h b/engines/director/window.h
index 7d8da5a219..1a07f85ffa 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -116,6 +116,7 @@ public:
 	Archive *getMainArchive() const { return _mainArchive; }
 	Movie *getCurrentMovie() const { return _currentMovie; }
 	Common::String getCurrentPath() const { return _currentPath; }
+	DirectorSound *getSoundManager() const { return _soundManager; }
 
 	virtual void setVisible(bool visible, bool silent = false) override;
 	bool setNextMovie(Common::String &movieFilenameRaw);
@@ -186,6 +187,7 @@ private:
 	uint32 _stageColor;
 
 	DirectorEngine *_vm;
+	DirectorSound *_soundManager;
 	bool _isStage;
 	Archive *_mainArchive;
 	Common::MacResManager *_macBinary;


Commit: a2e8da00e5f6924ce159b09450058418e1e42fc1
    https://github.com/scummvm/scummvm/commit/a2e8da00e5f6924ce159b09450058418e1e42fc1
Author: djsrv (dservilla at gmail.com)
Date: 2021-07-27T22:42:09-04:00

Commit Message:
DIRECTOR: Don't render next frame if exitFrame stopped the movie

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index d4e78f3c7a..57314800ac 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -359,6 +359,12 @@ void Score::update() {
 		}
 	}
 
+	_vm->_skipFrameAdvance = false;
+
+	// the exitFrame event handler may have stopped this movie
+	if (_playState == kPlayStopped)
+		return;
+
 	if (_nextFrame)
 		_currentFrame = _nextFrame;
 	else if (!_window->_newMovieStarted)
@@ -366,8 +372,6 @@ void Score::update() {
 
 	_nextFrame = 0;
 
-	_vm->_skipFrameAdvance = false;
-
 	if (_currentFrame >= _frames.size()) {
 		Window *window = _vm->getCurrentWindow();
 		if (!window->_movieStack.empty()) {


Commit: a16d823201282dfd882c1b583e32b35349d00046
    https://github.com/scummvm/scummvm/commit/a16d823201282dfd882c1b583e32b35349d00046
Author: djsrv (dservilla at gmail.com)
Date: 2021-07-27T22:54:16-04:00

Commit Message:
DIRECTOR: Improve puppetSound

Most variants of puppetSounds don't actually start the sound immediately
but wait until the frame is updated. So I've created a SoundID struct
which stores a reference to a cast member or externals sound, and that
is used to store the puppetSound until it's actually supposed to start.
In addition, puppet status is now per-channel instead of a universal
flag.

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/score.cpp
    engines/director/score.h
    engines/director/sound.cpp
    engines/director/sound.h


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index b62b9b89ed..5b7e405fcf 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1936,32 +1936,36 @@ void LB::b_puppetSound(int nargs) {
 		return;
 	}
 
-	sound->_puppet = true;
-	if (nargs == 1 || g_director->getVersion() >= 400) {
-		Datum castMember = g_lingo->pop();
+	// Most variants of puppetSound don't actually play the sound
+	// until the playback head moves or updateStage is called.
+	// So we'll just queue it to be played later.
 
-		// in D2 manual p206, puppetSound 0 will turn off the puppet status of sound
-		if (castMember.asInt() == 0)
-			sound->_puppet = false;
-
-		uint channel = 1;
-		if (nargs == 2)
-			channel = g_lingo->pop().asInt();
+	if (nargs == 1) {
+		CastMemberID castMember = g_lingo->pop().asMemberID();
 
-		sound->playCastMember(castMember.asMemberID(), channel);
+		// in D2 manual p206, puppetSound 0 will turn off the puppet status of sound
+		sound->setPuppetSound(castMember, 1);
 	} else {
-		// in D2/3/3.1 interactivity manual, 2 args represent the menu and submenu sounds
-		uint submenu = g_lingo->pop().asInt();
-		uint menu = g_lingo->pop().asInt();
+		if (g_director->getVersion() < 400) {
+			// in D2/3/3.1 interactivity manual, 2 args represent the menu and submenu sounds
+			int submenu = g_lingo->pop().asInt();
+			int menu = g_lingo->pop().asInt();
 
-		if (menu <= 9 || menu >= 16)
-			warning("LB::puppetSound: menu number is not available");
+			if (menu <= 9 || menu >= 16)
+				warning("LB::puppetSound: menu number is not available");
 
-		if (score->_sampleSounds.empty())
-			score->loadSampleSounds(menu);
-
-		if (submenu <= score->_sampleSounds.size())
-			sound->playExternalSound(score->_sampleSounds[submenu - 1], 1, submenu);
+			sound->setPuppetSound(SoundID(kSoundExternal, menu, submenu), 1);
+		} else {
+			// Two-argument puppetSound is undocumented in D4.
+			// It is however documented in the D5 Lingo dictionary.
+			CastMemberID castMember = g_lingo->pop().asMemberID();
+			int channel = g_lingo->pop().asInt();
+			sound->setPuppetSound(castMember, channel);
+
+			// The D4 two-arg variant of puppetSound plays
+			// immediately for some inexplicable reason.
+			sound->playPuppetSound(channel);
+		}
 	}
 }
 
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 57314800ac..09658daea5 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -92,9 +92,6 @@ Score::~Score() {
 		for (Common::SortedArray<Label *>::iterator it = _labels->begin(); it != _labels->end(); ++it)
 			delete *it;
 
-	for (uint i = 0; i < _sampleSounds.size(); i++)
-		delete _sampleSounds[i];
-
 	delete _labels;
 }
 
@@ -713,32 +710,27 @@ void Score::playSoundChannel(uint16 frameId) {
 	debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %s Sound2 %s", frame->_sound1.asString().c_str(), frame->_sound2.asString().c_str());
 	DirectorSound *sound = _window->getSoundManager();
 
-	// puppet sound will be controlled with lingo
-	if (sound->_puppet)
-		return;
-
-	// 0x0f represent sample sound
-	if (frame->_soundType1 >= 10 && frame->_soundType1 <= 15) {
-		if (_sampleSounds.empty())
-			loadSampleSounds(frame->_soundType1);
-
-		if ((uint)frame->_sound1.member <= _sampleSounds.size()) {
-			sound->playExternalSound(_sampleSounds[frame->_sound1.member - 1], 1, frame->_sound1.member);
-		}
+	if (sound->isChannelPuppet(1)) {
+		sound->playPuppetSound(1);
+	} else if (frame->_soundType1 >= 10 && frame->_soundType1 <= 15) { // 0x0f represent sample sound
+		sound->playExternalSound(frame->_soundType1, frame->_sound1.member, 1);
 	} else {
 		sound->playCastMember(frame->_sound1, 1, false);
 	}
 
-	if (frame->_soundType2 >= 10 && frame->_soundType2 <= 15) {
-		if (_sampleSounds.empty())
-			loadSampleSounds(frame->_soundType2);
-
-		if ((uint)frame->_sound2.member <= _sampleSounds.size()) {
-			sound->playExternalSound(_sampleSounds[frame->_sound2.member - 1], 2, frame->_sound2.member);
-		}
+	if (sound->isChannelPuppet(2)) {
+		sound->playPuppetSound(2);
+	} else if (frame->_soundType2 >= 10 && frame->_soundType2 <= 15) {
+		sound->playExternalSound(frame->_soundType2, frame->_sound2.member, 2);
 	} else {
 		sound->playCastMember(frame->_sound2, 2, false);
 	}
+
+	// Channels above 2 are only usable by Lingo.
+	if (g_director->getVersion() >= 400) {
+		sound->playPuppetSound(3);
+		sound->playPuppetSound(4);
+	}
 }
 
 void Score::playQueuedSound() {
@@ -746,53 +738,6 @@ void Score::playQueuedSound() {
 	sound->playFPlaySound();
 }
 
-void Score::loadSampleSounds(uint type) {
-	// trying to load external sample sounds
-	// lazy loading
-	uint32 tag = MKTAG('C', 'S', 'N', 'D');
-	uint id = 0xFF;
-	Archive *archive = nullptr;
-
-	for (Common::HashMap<Common::String, Archive *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator it = g_director->_openResFiles.begin(); it != g_director->_openResFiles.end(); ++it) {
-		Common::Array<uint16> idList = it->_value->getResourceIDList(tag);
-		for (uint j = 0; j < idList.size(); j++) {
-			if ((idList[j] & 0xFF) == type) {
-				id = idList[j];
-				archive = it->_value;
-				break;
-			}
-		}
-	}
-
-	if (id == 0xFF) {
-		warning("Score::loadSampleSounds: can not find CSND resource with id %d", type);
-		return;
-	}
-
-	Common::SeekableReadStreamEndian *csndData = archive->getResource(tag, id);
-
-	/*uint32 flag = */ csndData->readUint32();
-
-	// the flag should be 0x604E
-	// i'm not sure what's that mean, but it occurs in those csnd files
-
-	// contains how many csnd data
-	uint16 num = csndData->readUint16();
-
-	// read the offset first;
-	Common::Array<uint32> offset(num);
-	for (uint i = 0; i < num; i++)
-		offset[i] = csndData->readUint32();
-
-	for (uint i = 0; i < num; i++) {
-		csndData->seek(offset[i]);
-
-		SNDDecoder *ad = new SNDDecoder();
-		ad->loadExternalSoundStream(*csndData);
-		_sampleSounds.push_back(ad);
-	}
-}
-
 void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version) {
 	debugC(1, kDebugLoading, "****** Loading frames VWSC");
 
diff --git a/engines/director/score.h b/engines/director/score.h
index a1d707a991..fc102d6cab 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -129,7 +129,6 @@ public:
 	Common::SortedArray<Label *> *_labels;
 	Common::HashMap<uint16, Common::String> _actions;
 	Common::HashMap<uint16, bool> _immediateActions;
-	Common::Array<AudioDecoder *> _sampleSounds;
 
 	byte _currentFrameRate;
 
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 8b1975429f..643ae36fbf 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -57,11 +57,11 @@ DirectorSound::DirectorSound(Window *window) : _window(window) {
 		&_pcSpeakerHandle, _speaker, -1, 50, 0, DisposeAfterUse::NO, true);
 
 	_enable = true;
-	_puppet = false;
 }
 
 DirectorSound::~DirectorSound() {
 	this->stopSound();
+	unloadSampleSounds();
 	delete _speaker;
 }
 
@@ -104,6 +104,17 @@ void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, &stream, -1, getChannelVolume(soundChannel));
 }
 
+void DirectorSound::playSound(SoundID soundID, uint8 soundChannel) {
+	switch (soundID.type) {
+	case kSoundCast:
+		playCastMember(CastMemberID(soundID.u.cast.member, soundID.u.cast.castLib), soundChannel);
+		break;
+	case kSoundExternal:
+		playExternalSound(soundID.u.external.menu, soundID.u.external.submenu, soundChannel);
+		break;
+	}
+}
+
 void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat) {
 	if (!isChannelValid(soundChannel))
 		return;
@@ -116,7 +127,7 @@ void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bo
 			if (soundCast->_type != kCastSound) {
 				warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember %s", memberID.asString().c_str());
 			} else {
-				if (!allowRepeat && checkLastPlayCast(soundChannel, memberID))
+				if (!allowRepeat && checkLastPlaySound(soundChannel, memberID))
 					return;
 				bool looping = ((SoundCastMember *)soundCast)->_looping;
 				AudioDecoder *ad = ((SoundCastMember *)soundCast)->_audio;
@@ -133,7 +144,7 @@ void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bo
 					return;
 				}
 				playStream(*as, soundChannel);
-				setLastPlayCast(soundChannel, memberID);
+				setLastPlaySound(soundChannel, memberID);
 			}
 		} else {
 			warning("DirectorSound::playCastMember: couldn't find %s", memberID.asString().c_str());
@@ -251,31 +262,99 @@ bool DirectorSound::isChannelValid(uint8 soundChannel) {
 	return true;
 }
 
-void DirectorSound::playExternalSound(AudioDecoder *ad, uint8 soundChannel, uint8 externalSoundID) {
+void DirectorSound::loadSampleSounds(uint type) {
+	if (_sampleSounds.contains(type))
+		return;
+
+	_sampleSounds[type] = Common::Array<AudioDecoder *>();
+
+	// trying to load external sample sounds
+	// lazy loading
+	uint32 tag = MKTAG('C', 'S', 'N', 'D');
+	uint id = 0xFF;
+	Archive *archive = nullptr;
+
+	for (Common::HashMap<Common::String, Archive *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator it = g_director->_openResFiles.begin(); it != g_director->_openResFiles.end(); ++it) {
+		Common::Array<uint16> idList = it->_value->getResourceIDList(tag);
+		for (uint j = 0; j < idList.size(); j++) {
+			if ((idList[j] & 0xFF) == type) {
+				id = idList[j];
+				archive = it->_value;
+				break;
+			}
+		}
+	}
+
+	if (id == 0xFF) {
+		warning("Score::loadSampleSounds: can not find CSND resource with id %d", type);
+		return;
+	}
+
+	Common::SeekableReadStreamEndian *csndData = archive->getResource(tag, id);
+
+	/*uint32 flag = */ csndData->readUint32();
+
+	// the flag should be 0x604E
+	// i'm not sure what's that mean, but it occurs in those csnd files
+
+	// contains how many csnd data
+	uint16 num = csndData->readUint16();
+
+	// read the offset first;
+	Common::Array<uint32> offset(num);
+	for (uint i = 0; i < num; i++)
+		offset[i] = csndData->readUint32();
+
+	for (uint i = 0; i < num; i++) {
+		csndData->seek(offset[i]);
+
+		SNDDecoder *ad = new SNDDecoder();
+		ad->loadExternalSoundStream(*csndData);
+		_sampleSounds[type].push_back(ad);
+	}
+}
+
+void DirectorSound::unloadSampleSounds() {
+	for (Common::HashMap<uint, Common::Array<AudioDecoder *>>::iterator it = _sampleSounds.begin(); it != _sampleSounds.end(); ++it)
+		for (uint i = 0; i < it->_value.size(); i++)
+			delete it->_value[i];
+	
+	_sampleSounds.clear();
+}
+
+void DirectorSound::playExternalSound(uint16 menu, uint16 submenu, uint8 soundChannel) {
 	if (!isChannelValid(soundChannel))
 		return;
 
-	// use castMemberID info to check, castLib -1 represent for externalSound
-	// this should be amended by some kind of union which contains CastMemberID and externalSound info
-	if (isChannelActive(soundChannel) && checkLastPlayCast(soundChannel, CastMemberID(externalSoundID, -1)))
+	SoundID soundId(kSoundExternal, menu, submenu);
+	if (isChannelActive(soundChannel) && checkLastPlaySound(soundChannel, soundId))
 		return;
 
-	playStream(*(ad->getAudioStream()), soundChannel);
-	setLastPlayCast(soundChannel, CastMemberID(externalSoundID, -1));
+	if (!_sampleSounds.contains(menu))
+		loadSampleSounds(menu);
+
+	if ((uint)submenu<= _sampleSounds[menu].size()) {
+		playStream(*(_sampleSounds[menu][submenu - 1]->getAudioStream()), soundChannel);
+		setLastPlaySound(soundChannel, soundId);
+	} else {
+		warning("DirectorSound::playExternalSound: Could not find sound %d %d", menu, submenu);
+	}
 }
 
 void DirectorSound::changingMovie() {
-	for (uint i = 0; i < _channels.size(); i++)
+	for (uint i = 0; i < _channels.size(); i++) {
 		_channels[i]._movieChanged = true;
+	}
+	unloadSampleSounds(); // TODO: we can possibly keep this between movies
 }
 
-void DirectorSound::setLastPlayCast(uint8 soundChannel, CastMemberID castMemberId) {
-	_channels[soundChannel - 1].lastPlayingCast = castMemberId;
+void DirectorSound::setLastPlaySound(uint8 soundChannel, SoundID soundId) {
+	_channels[soundChannel - 1].lastPlayingSound = soundId;
 	_channels[soundChannel - 1]._movieChanged = false;
 }
 
-bool DirectorSound::checkLastPlayCast(uint8 soundChannel, const CastMemberID &castMemberId) {
-	return !_channels[soundChannel - 1]._movieChanged && _channels[soundChannel - 1].lastPlayingCast == castMemberId;
+bool DirectorSound::checkLastPlaySound(uint8 soundChannel, const SoundID &soundId) {
+	return !_channels[soundChannel - 1]._movieChanged && _channels[soundChannel - 1].lastPlayingSound == soundId;
 }
 
 void DirectorSound::stopSound(uint8 soundChannel) {
@@ -284,7 +363,7 @@ void DirectorSound::stopSound(uint8 soundChannel) {
 
 	cancelFade(soundChannel);
 	_mixer->stopHandle(_channels[soundChannel - 1].handle);
-	setLastPlayCast(soundChannel, CastMemberID(0, 0));
+	setLastPlaySound(soundChannel, SoundID());
 	return;
 }
 
@@ -293,7 +372,7 @@ void DirectorSound::stopSound() {
 		cancelFade(i + 1);
 
 		_mixer->stopHandle(_channels[i].handle);
-		setLastPlayCast(i + 1, CastMemberID(0, 0));
+		setLastPlaySound(i + 1, SoundID());
 	}
 
 	_mixer->stopHandle(_scriptSound);
@@ -304,6 +383,37 @@ void DirectorSound::systemBeep() {
 	_speaker->play(Audio::PCSpeaker::kWaveFormSquare, 500, 150);
 }
 
+bool DirectorSound::isChannelPuppet(uint8 soundChannel) {
+	if (!isChannelValid(soundChannel))
+		return false;
+
+	// cast member ID 0 means "not a puppet"
+	if (_channels[soundChannel - 1].puppet.type == kSoundCast && _channels[soundChannel - 1].puppet.u.cast.member == 0)
+		return false;
+
+	return true;
+}
+
+void DirectorSound::setPuppetSound(SoundID soundId, uint8 soundChannel) {
+	if (!isChannelValid(soundChannel))
+		return;
+
+	_channels[soundChannel - 1].newPuppet = true;
+	_channels[soundChannel - 1].puppet = soundId;
+}
+
+void DirectorSound::playPuppetSound(uint8 soundChannel) {
+	if (!isChannelValid(soundChannel))
+		return;
+
+	// only play if the puppet was just set
+	if (!_channels[soundChannel - 1].newPuppet)
+		return;
+
+	_channels[soundChannel - 1].newPuppet = false;
+	playSound(_channels[soundChannel - 1].puppet, soundChannel);
+}
+
 void DirectorSound::playFPlaySound() {
 	if (_fplayQueue.empty())
 		return;
diff --git a/engines/director/sound.h b/engines/director/sound.h
index d714ddaaa7..0aec657309 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -48,25 +48,100 @@ struct FadeParams {
 		startVol(sv), targetVol(tv), totalTicks(tt), startTicks(st), lapsedTicks(0), fadeIn(f) {}
 };
 
+struct ExternalSoundID {
+	uint16 menu;
+	uint16 submenu;
+
+	ExternalSoundID() : menu(0), submenu(0) {}
+	ExternalSoundID(uint16 menuID, uint16 submenuID)
+		: menu(menuID), submenu(submenuID) {}
+
+	bool operator==(const ExternalSoundID &b) {
+		return menu == b.menu && submenu == b.submenu;
+	}
+	bool operator!=(const ExternalSoundID &b) {
+		return !(*this == b);
+	}
+};
+
+enum SoundIDType {
+	kSoundCast,
+	kSoundExternal
+};
+
+struct SoundID {
+	SoundIDType type;
+	union {
+		struct {
+			int member;
+			int castLib;
+		} cast;
+		struct {
+			uint16 menu;
+			uint16 submenu;
+		} external;
+	} u;
+
+	SoundID() {
+		type = kSoundCast;
+		u.cast.member = 0;
+		u.cast.castLib = 0;
+	}
+	SoundID(SoundIDType type_, int a, int b) {
+		type = type_;
+		switch (type) {
+		case kSoundCast:
+			u.cast.member = a;
+			u.cast.castLib = b;
+			break;
+		case kSoundExternal:
+			u.external.menu = a;
+			u.external.submenu = b;
+		}
+	}
+	SoundID(CastMemberID memberID) {
+		type = kSoundCast;
+		u.cast.member = memberID.member;
+		u.cast.castLib = memberID.castLib;
+	}
+
+	bool operator==(const SoundID &b) {
+		if (type != b.type)
+			return false;
+
+		switch (type) {
+		case kSoundCast:
+			return u.cast.member == b.u.cast.member && u.cast.castLib == b.u.cast.castLib;
+		case kSoundExternal:
+			return u.external.menu == b.u.external.menu && u.external.submenu == b.u.external.submenu;
+		}
+
+		return false;
+	}
+	bool operator!=(const SoundID &b) {
+		return !(*this == b);
+	}
+};
+
 struct SoundChannel {
 	Audio::SoundHandle handle;
-	CastMemberID lastPlayingCast;
+	SoundID lastPlayingSound;
 	byte volume;
 	FadeParams *fade;
 
+	// a non-zero sound ID if the channel is a puppet. i.e. it's controlled by lingo
+	SoundID puppet;
+	bool newPuppet;
+
 	// this indicate whether the sound is playing across the movie. Because the cast name may be the same while the actual sounds are changing.
 	// And we will override the sound when ever the sound is changing. thus we use a flag to indicate whether the movie is changed.
 	bool _movieChanged;
 
-	SoundChannel(): handle(), volume(255), fade(nullptr), _movieChanged(false) {}
+	SoundChannel(): handle(), lastPlayingSound(SoundID()), volume(255), fade(nullptr), puppet(SoundID()), newPuppet(false), _movieChanged(false) {}
 };
 
 class DirectorSound {
 
-public:
-	// whether the sound is puppet. i.e. it's controlled by lingo
-	bool _puppet;
-
 private:
 	Window *_window;
 	Common::Array<SoundChannel> _channels;
@@ -81,6 +156,8 @@ private:
 
 	bool _enable;
 
+	Common::HashMap<uint, Common::Array<AudioDecoder *>> _sampleSounds;
+
 public:
 	DirectorSound(Window *window);
 	~DirectorSound();
@@ -89,8 +166,9 @@ public:
 	void playFile(Common::String filename, uint8 soundChannel);
 	void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
 	void playStream(Audio::AudioStream &stream, uint8 soundChannel);
+	void playSound(SoundID soundId, uint8 soundChannel);
 	void playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat = true);
-	void playExternalSound(AudioDecoder *ad, uint8 soundChannel, uint8 externalSoundID);
+	void playExternalSound(uint16 menu, uint16 submenu, uint8 soundChannel);
 	void playFPlaySound(const Common::Array<Common::String> &fplayList);
 	void playFPlaySound();
 	void setSouldLevel(int channel, uint8 soundLevel);
@@ -99,8 +177,15 @@ public:
 	void systemBeep();
 	void changingMovie();
 
-	void setLastPlayCast(uint8 soundChannel, CastMemberID castMemberId);
-	bool checkLastPlayCast(uint8 soundChannel, const CastMemberID &castMemberId);
+	void loadSampleSounds(uint type);
+	void unloadSampleSounds();
+
+	void setLastPlaySound(uint8 soundChannel, SoundID soundId);
+	bool checkLastPlaySound(uint8 soundChannel, const SoundID &soundId);
+
+	bool isChannelPuppet(uint8 soundChannel);
+	void setPuppetSound(SoundID soundId, uint8 soundChannel);
+	void playPuppetSound(uint8 soundChannel);
 
 	bool getSoundEnabled() { return _enable; }
 


Commit: ff16d808c7cbb1aad84aae1999c60747ee66ae4b
    https://github.com/scummvm/scummvm/commit/ff16d808c7cbb1aad84aae1999c60747ee66ae4b
Author: djsrv (dservilla at gmail.com)
Date: 2021-07-27T22:54:25-04:00

Commit Message:
DIRECTOR: LINGO: Play puppet sounds in updateStage

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/score.h


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 5b7e405fcf..c9fc1d0d34 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -2232,6 +2232,9 @@ void LB::b_updateStage(int nargs) {
 	if (movie->getWindow()->render())
 		g_director->draw();
 
+	// play any puppet sounds that have been queued
+	score->playSoundChannel(score->getCurrentFrame());
+
 	if (debugChannelSet(-1, kDebugFewFramesOnly)) {
 		score->_framesRan++;
 
diff --git a/engines/director/score.h b/engines/director/score.h
index fc102d6cab..d34d3d03b5 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -113,10 +113,10 @@ public:
 	void renderCursor(Common::Point pos);
 	void renderVideo();
 
+	void playSoundChannel(uint16 frameId);
+
 private:
 	void update();
-
-	void playSoundChannel(uint16 frameId);
 	void playQueuedSound();
 
 	void screenShot();


Commit: 00a1ba2ee875fb0421ab383a0148e9fdfa95d384
    https://github.com/scummvm/scummvm/commit/00a1ba2ee875fb0421ab383a0148e9fdfa95d384
Author: djsrv (dservilla at gmail.com)
Date: 2021-07-27T22:54:25-04:00

Commit Message:
DIRECTOR: Disable puppet sounds when the movie changes

Changed paths:
    engines/director/sound.cpp


diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 643ae36fbf..c14bb633cb 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -343,6 +343,7 @@ void DirectorSound::playExternalSound(uint16 menu, uint16 submenu, uint8 soundCh
 
 void DirectorSound::changingMovie() {
 	for (uint i = 0; i < _channels.size(); i++) {
+		setPuppetSound(SoundID(), i + 1); // disable puppet sound
 		_channels[i]._movieChanged = true;
 	}
 	unloadSampleSounds(); // TODO: we can possibly keep this between movies




More information about the Scummvm-git-logs mailing list