[Scummvm-git-logs] scummvm master -> 1493ca291bf2d362a25cdf470fbe8b0e7f6cb95b

djsrv dservilla at gmail.com
Sat Aug 7 17:20:53 UTC 2021


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

Summary:
0b39f10a08 DIRECTOR: Change _movieChanged to movieChanged
1493ca291b DIRECTOR: Improve empty sound channel behavior


Commit: 0b39f10a08a99dbe6e69cc3b97cecf4491f1e529
    https://github.com/scummvm/scummvm/commit/0b39f10a08a99dbe6e69cc3b97cecf4491f1e529
Author: djsrv (dservilla at gmail.com)
Date: 2021-08-07T13:20:23-04:00

Commit Message:
DIRECTOR: Change _movieChanged to movieChanged

Changed paths:
    engines/director/sound.cpp
    engines/director/sound.h


diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 816dc7d98f..b9c38e4321 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -356,18 +356,18 @@ 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;
+		_channels[i].movieChanged = true;
 	}
 	unloadSampleSounds(); // TODO: we can possibly keep this between movies
 }
 
 void DirectorSound::setLastPlaySound(uint8 soundChannel, SoundID soundId) {
 	_channels[soundChannel - 1].lastPlayingSound = soundId;
-	_channels[soundChannel - 1]._movieChanged = false;
+	_channels[soundChannel - 1].movieChanged = false;
 }
 
 bool DirectorSound::checkLastPlaySound(uint8 soundChannel, const SoundID &soundId) {
-	return !_channels[soundChannel - 1]._movieChanged && _channels[soundChannel - 1].lastPlayingSound == soundId;
+	return !_channels[soundChannel - 1].movieChanged && _channels[soundChannel - 1].lastPlayingSound == soundId;
 }
 
 void DirectorSound::stopSound(uint8 soundChannel) {
diff --git a/engines/director/sound.h b/engines/director/sound.h
index 9052a70ae2..900050beca 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -139,9 +139,9 @@ struct SoundChannel {
 
 	// 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;
+	bool movieChanged;
 
-	SoundChannel(): handle(), lastPlayingSound(SoundID()), volume(255), fade(nullptr), puppet(SoundID()), newPuppet(false), _movieChanged(false) {}
+	SoundChannel(): handle(), lastPlayingSound(SoundID()), volume(255), fade(nullptr), puppet(SoundID()), newPuppet(false), movieChanged(false) {}
 };
 
 class DirectorSound {


Commit: 1493ca291bf2d362a25cdf470fbe8b0e7f6cb95b
    https://github.com/scummvm/scummvm/commit/1493ca291bf2d362a25cdf470fbe8b0e7f6cb95b
Author: djsrv (dservilla at gmail.com)
Date: 2021-08-07T13:20:23-04:00

Commit Message:
DIRECTOR: Improve empty sound channel behavior

Changed paths:
    engines/director/score.cpp
    engines/director/sound.cpp
    engines/director/sound.h


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index cf0616a561..4e5be0a8d1 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -727,7 +727,7 @@ void Score::playSoundChannel(uint16 frameId) {
 	} else if (frame->_soundType1 >= kMinSampledMenu && frame->_soundType1 <= kMaxSampledMenu) {
 		sound->playExternalSound(frame->_soundType1, frame->_sound1.member, 1);
 	} else {
-		sound->playCastMember(frame->_sound1, 1, false);
+		sound->playCastMember(frame->_sound1, 1);
 	}
 
 	if (sound->isChannelPuppet(2)) {
@@ -735,7 +735,7 @@ void Score::playSoundChannel(uint16 frameId) {
 	} else if (frame->_soundType2 >= kMinSampledMenu && frame->_soundType2 <= kMaxSampledMenu) {
 		sound->playExternalSound(frame->_soundType2, frame->_sound2.member, 2);
 	} else {
-		sound->playCastMember(frame->_sound2, 2, false);
+		sound->playCastMember(frame->_sound2, 2);
 	}
 
 	// Channels above 2 are only usable by Lingo.
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index b9c38e4321..d8dbdede4f 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -76,10 +76,13 @@ void DirectorSound::playFile(Common::String filename, uint8 soundChannel) {
 		return;
 
 	AudioFileDecoder af(filename);
-	Audio::AudioStream *sound = af.getAudioStream(false, DisposeAfterUse::YES);
+	Audio::AudioStream *sound = af.getAudioStream(false, false, DisposeAfterUse::YES);
 
 	cancelFade(soundChannel);
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, sound, -1, getChannelVolume(soundChannel));
+
+	// Set the last played sound so that cast member 0 in the sound channel doesn't stop this file.
+	setLastPlayedSound(soundChannel, SoundID(), false);
 }
 
 void DirectorSound::playMCI(Audio::AudioStream &stream, uint32 from, uint32 to) {
@@ -104,10 +107,10 @@ 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) {
+void DirectorSound::playSound(SoundID soundID, uint8 soundChannel, bool forPuppet) {
 	switch (soundID.type) {
 	case kSoundCast:
-		playCastMember(CastMemberID(soundID.u.cast.member, soundID.u.cast.castLib), soundChannel);
+		playCastMember(CastMemberID(soundID.u.cast.member, soundID.u.cast.castLib), soundChannel, forPuppet);
 		break;
 	case kSoundExternal:
 		playExternalSound(soundID.u.external.menu, soundID.u.external.submenu, soundChannel);
@@ -115,21 +118,47 @@ void DirectorSound::playSound(SoundID soundID, uint8 soundChannel) {
 	}
 }
 
-void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat) {
+void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bool forPuppet) {
 	if (!isChannelValid(soundChannel))
 		return;
 
 	if (memberID.member == 0) {
-		stopSound(soundChannel);
+		// Normally cast member 0 stops the sound.
+		// But there are some sounds where it doesn't. Those are:
+		//   1. playFile
+		//   2. FPlay
+		//   3. non-puppet looping sounds
+		//   4. maybe more?
+		if (shouldStopOnZero(soundChannel)) {
+			stopSound(soundChannel);
+		} else {
+			// Don't stop the currently playing sound, just set the last played sound to 0.
+			setLastPlayedSound(soundChannel, SoundID(), false);
+		}
 	} else {
 		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());
 			} else {
-				if (!allowRepeat && checkLastPlaySound(soundChannel, memberID))
-					return;
 				bool looping = ((SoundCastMember *)soundCast)->_looping;
+				bool stopOnZero = true;
+
+				if (!forPuppet && isLastPlayedSound(soundChannel, memberID)) {
+					// We just played this sound.
+					// If the sound is not marked "looping", we should not play it again.
+					if (!looping)
+						return;
+
+					// If the sound is not finished yet, we need to wait more before playing it again.
+					if (isChannelActive(soundChannel))
+						return;
+
+					// We know that this is a non-puppet, looping sound.
+					// We don't want to stop it if this channel's cast member changes to 0.
+					stopOnZero = false;
+				}
+
 				AudioDecoder *ad = ((SoundCastMember *)soundCast)->_audio;
 				if (!ad) {
 					warning("DirectorSound::playCastMember: no audio data attached to %s", memberID.asString().c_str());
@@ -137,14 +166,14 @@ void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bo
 				}
 
 				Audio::AudioStream *as;
-				as = ad->getAudioStream(looping);
+				as = ad->getAudioStream(looping, forPuppet);
 
 				if (!as) {
 					warning("DirectorSound::playCastMember: audio data failed to load from cast");
 					return;
 				}
 				playStream(*as, soundChannel);
-				setLastPlaySound(soundChannel, memberID);
+				setLastPlayedSound(soundChannel, memberID, stopOnZero);
 			}
 		} else {
 			warning("DirectorSound::playCastMember: couldn't find %s", memberID.asString().c_str());
@@ -333,7 +362,7 @@ void DirectorSound::playExternalSound(uint16 menu, uint16 submenu, uint8 soundCh
 		return;
 
 	SoundID soundId(kSoundExternal, menu, submenu);
-	if (isChannelActive(soundChannel) && checkLastPlaySound(soundChannel, soundId))
+	if (isChannelActive(soundChannel) && isLastPlayedSound(soundChannel, soundId))
 		return;
 
 	if (menu < kMinSampledMenu || menu > kMaxSampledMenu) {
@@ -347,7 +376,7 @@ void DirectorSound::playExternalSound(uint16 menu, uint16 submenu, uint8 soundCh
 
 	if (1 <= submenu && submenu <= menuSounds.size()) {
 		playStream(*(menuSounds[submenu - 1]->getAudioStream()), soundChannel);
-		setLastPlaySound(soundChannel, soundId);
+		setLastPlayedSound(soundChannel, soundId);
 	} else {
 		warning("DirectorSound::playExternalSound: Could not find sound %d %d", menu, submenu);
 	}
@@ -361,13 +390,18 @@ void DirectorSound::changingMovie() {
 	unloadSampleSounds(); // TODO: we can possibly keep this between movies
 }
 
-void DirectorSound::setLastPlaySound(uint8 soundChannel, SoundID soundId) {
-	_channels[soundChannel - 1].lastPlayingSound = soundId;
+void DirectorSound::setLastPlayedSound(uint8 soundChannel, SoundID soundId, bool stopOnZero) {
+	_channels[soundChannel - 1].lastPlayedSound = soundId;
+	_channels[soundChannel - 1].stopOnZero = stopOnZero;
 	_channels[soundChannel - 1].movieChanged = false;
 }
 
-bool DirectorSound::checkLastPlaySound(uint8 soundChannel, const SoundID &soundId) {
-	return !_channels[soundChannel - 1].movieChanged && _channels[soundChannel - 1].lastPlayingSound == soundId;
+bool DirectorSound::isLastPlayedSound(uint8 soundChannel, const SoundID &soundId) {
+	return !_channels[soundChannel - 1].movieChanged && _channels[soundChannel - 1].lastPlayedSound == soundId;
+}
+
+bool DirectorSound::shouldStopOnZero(uint8 soundChannel) {
+	return _channels[soundChannel - 1].stopOnZero;
 }
 
 void DirectorSound::stopSound(uint8 soundChannel) {
@@ -376,7 +410,7 @@ void DirectorSound::stopSound(uint8 soundChannel) {
 
 	cancelFade(soundChannel);
 	_mixer->stopHandle(_channels[soundChannel - 1].handle);
-	setLastPlaySound(soundChannel, SoundID());
+	setLastPlayedSound(soundChannel, SoundID());
 	return;
 }
 
@@ -385,7 +419,7 @@ void DirectorSound::stopSound() {
 		cancelFade(i + 1);
 
 		_mixer->stopHandle(_channels[i].handle);
-		setLastPlaySound(i + 1, SoundID());
+		setLastPlayedSound(i + 1, SoundID());
 	}
 
 	_mixer->stopHandle(_scriptSound);
@@ -424,7 +458,7 @@ void DirectorSound::playPuppetSound(uint8 soundChannel) {
 		return;
 
 	_channels[soundChannel - 1].newPuppet = false;
-	playSound(_channels[soundChannel - 1].puppet, soundChannel);
+	playSound(_channels[soundChannel - 1].puppet, soundChannel, true);
 }
 
 void DirectorSound::playFPlaySound() {
@@ -476,7 +510,10 @@ void DirectorSound::playFPlaySound() {
 			_fplayQueue.pop();
 			looping = true;
 		}
-		as = ad->getAudioStream(looping);
+
+		// FPlay is controlled by Lingo, not the score, like a puppet,
+		// so we'll get the puppet version of the stream.
+		as = ad->getAudioStream(looping, true);
 
 		if (!as) {
 			warning("DirectorSound:playFPlaySound: failed to get audio stream");
@@ -489,6 +526,9 @@ void DirectorSound::playFPlaySound() {
 		playStream(*as, 1);
 		delete ad;
 	}
+
+	// Set the last played sound so that cast member 0 in the sound channel doesn't stop this file.
+	setLastPlayedSound(1, SoundID(), false);
 }
 
 void DirectorSound::playFPlaySound(const Common::Array<Common::String> &fplayList) {
@@ -673,7 +713,7 @@ bool SNDDecoder::processBufferCommand(Common::SeekableReadStreamEndian &stream)
 	return true;
 }
 
-Audio::AudioStream *SNDDecoder::getAudioStream(bool looping, DisposeAfterUse::Flag disposeAfterUse) {
+Audio::AudioStream *SNDDecoder::getAudioStream(bool looping, bool forPuppet, DisposeAfterUse::Flag disposeAfterUse) {
 	if (!_data)
 		return nullptr;
 	byte *buffer = (byte *)malloc(_size);
@@ -683,12 +723,20 @@ Audio::AudioStream *SNDDecoder::getAudioStream(bool looping, DisposeAfterUse::Fl
 
 	if (looping) {
 		if (hasLoopBounds()) {
-			return new Audio::SubLoopingAudioStream(stream, 0, Audio::Timestamp(0, _loopStart, _rate), Audio::Timestamp(0, _loopEnd, _rate));
+			// If this is for a puppet, return an automatically looping stream.
+			// Otherwise, the sound will be looped by the score.
+			if (forPuppet)
+				return new Audio::SubLoopingAudioStream(stream, 0, Audio::Timestamp(0, _loopStart, _rate), Audio::Timestamp(0, _loopEnd, _rate));
+			else
+				return new Audio::SubSeekableAudioStream(stream, Audio::Timestamp(0, _loopStart, _rate), Audio::Timestamp(0, _loopEnd, _rate));
 		} else {
 			// Not sure if looping sounds can appear without loop bounds.
 			// Let's just log a warning and loop the entire sound...
 			warning("SNDDecoder::getAudioStream: Looping sound has no loop bounds");
-			return new Audio::LoopingAudioStream(stream, 0);
+			if (forPuppet)
+				return new Audio::LoopingAudioStream(stream, 0);
+			else
+				return stream;
 		}
 	}
 
@@ -704,7 +752,7 @@ AudioFileDecoder::AudioFileDecoder(Common::String &path)
 	_path = path;
 }
 
-Audio::AudioStream *AudioFileDecoder::getAudioStream(bool looping, DisposeAfterUse::Flag disposeAfterUse) {
+Audio::AudioStream *AudioFileDecoder::getAudioStream(bool looping, bool forPuppet, DisposeAfterUse::Flag disposeAfterUse) {
 	if (_path.empty())
 		return nullptr;
 
@@ -730,10 +778,12 @@ Audio::AudioStream *AudioFileDecoder::getAudioStream(bool looping, DisposeAfterU
 	}
 
 	if (stream) {
-		if (looping)
-			return new Audio::LoopingAudioStream(stream, 0);
-		else
-			return stream;
+		if (looping && forPuppet) {
+			// If this is for a puppet, return an automatically looping stream.
+			// Otherwise, the sound will be looped by the score
+				return new Audio::LoopingAudioStream(stream, 0);
+		}
+		return stream;
 	}
 
 	return nullptr;
diff --git a/engines/director/sound.h b/engines/director/sound.h
index 900050beca..81f1848685 100644
--- a/engines/director/sound.h
+++ b/engines/director/sound.h
@@ -129,7 +129,8 @@ struct SoundID {
 
 struct SoundChannel {
 	Audio::SoundHandle handle;
-	SoundID lastPlayingSound;
+	SoundID lastPlayedSound;
+	bool stopOnZero; // Should the sound be stopped when the channel contains cast member 0?
 	byte volume;
 	FadeParams *fade;
 
@@ -141,7 +142,7 @@ struct SoundChannel {
 	// 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(), lastPlayingSound(SoundID()), volume(255), fade(nullptr), puppet(SoundID()), newPuppet(false), movieChanged(false) {}
+	SoundChannel(): handle(), lastPlayedSound(SoundID()), stopOnZero(true), volume(255), fade(nullptr), puppet(SoundID()), newPuppet(false), movieChanged(false) {}
 };
 
 class DirectorSound {
@@ -170,8 +171,8 @@ 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 playSound(SoundID soundId, uint8 soundChannel, bool forPuppet = false);
+	void playCastMember(CastMemberID memberID, uint8 soundChannel, bool forPuppet = false);
 	void playExternalSound(uint16 menu, uint16 submenu, uint8 soundChannel);
 	void playFPlaySound(const Common::Array<Common::String> &fplayList);
 	void playFPlaySound();
@@ -184,8 +185,9 @@ public:
 	void loadSampleSounds(uint type);
 	void unloadSampleSounds();
 
-	void setLastPlaySound(uint8 soundChannel, SoundID soundId);
-	bool checkLastPlaySound(uint8 soundChannel, const SoundID &soundId);
+	void setLastPlayedSound(uint8 soundChannel, SoundID soundId, bool stopOnZero = true);
+	bool isLastPlayedSound(uint8 soundChannel, const SoundID &soundId);
+	bool shouldStopOnZero(uint8 soundChannel);
 
 	bool isChannelPuppet(uint8 soundChannel);
 	void setPuppetSound(SoundID soundId, uint8 soundChannel);
@@ -214,7 +216,7 @@ public:
 	AudioDecoder() {};
 	virtual ~AudioDecoder() {};
 public:
-	virtual Audio::AudioStream *getAudioStream(bool looping = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) { return nullptr; }
+	virtual Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) { return nullptr; }
 };
 
 class SNDDecoder : public AudioDecoder {
@@ -226,7 +228,7 @@ public:
 	void loadExternalSoundStream(Common::SeekableReadStreamEndian &stream);
 	bool processCommands(Common::SeekableReadStreamEndian &stream);
 	bool processBufferCommand(Common::SeekableReadStreamEndian &stream);
-	Audio::AudioStream *getAudioStream(bool looping = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
+	Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
 	bool hasLoopBounds();
 
 private:
@@ -246,7 +248,7 @@ public:
 
 	void setPath(Common::String &path);
 
-	Audio::AudioStream *getAudioStream(bool looping = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
+	Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
 
 private:
 	Common::String _path;




More information about the Scummvm-git-logs mailing list