From 4368a4f69dad822ae45901fd6066049454a5ec58 Mon Sep 17 00:00:00 2001 From: Coen Rampen Date: Thu, 23 Nov 2023 22:08:23 +0100 Subject: [PATCH] LURE: Fix duplicate looping sounds Under some circumstances, looping sounds could be repeatedly triggered and multiple copies of the same sound would stack up and consume all the sound channels. Additionally, this could cause a crash because the code did not deal well with this situation. The engine will now check if a sound is already playing before adding it when loading a savegame. It will also not try to play a sound if not enough channels are available. --- engines/lure/sound.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp index 1e42685aa48..08677a90acf 100644 --- a/engines/lure/sound.cpp +++ b/engines/lure/sound.cpp @@ -114,7 +114,7 @@ void SoundManager::loadFromStream(Common::ReadStream *stream) { SoundDescResource &rec = soundDescs()[soundIndex]; if ((rec.flags & SF_RESTORE) != 0) // Requeue the sound for playing - addSound(soundIndex, false); + addSound2(soundIndex); } } } @@ -542,13 +542,14 @@ void SoundManager::musicInterface_Play(uint8 soundNumber, bool isMusic, uint8 nu } } } - if (source == -1) + if (source == -1) { warning("Insufficient sources to play sound %i", soundNumber); - else + } else { _sourcesInUse[source] = true; - MidiMusic *sound = new MidiMusic(_driver, soundNum, isMusic, - loop, source, numChannels, soundStart, dataSize, volume); - _playingSounds.push_back(MusicList::value_type(sound)); + MidiMusic *sound = new MidiMusic(_driver, soundNum, isMusic, + loop, source, numChannels, soundStart, dataSize, volume); + _playingSounds.push_back(MusicList::value_type(sound)); + } _soundMutex.unlock(); } @@ -801,8 +802,13 @@ void MidiMusic::setVolume(int volume) { void MidiMusic::playMusic() { debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::PlayMusic playing sound %d", _soundNumber); - if (Sound.isRoland() && !_isMusic) - _mt32Driver->allocateSourceChannels(_source, _numChannels); + if (Sound.isRoland() && !_isMusic) { + bool result = _mt32Driver->allocateSourceChannels(_source, _numChannels); + if (!result) { + stopMusic(); + return; + } + } _parser->loadMusic(_soundData, _soundSize); _parser->setTrack(0); _isPlaying = true;