diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 73c20ee6df1f..9d3e5f67f588 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -73,7 +73,7 @@ bool Sound::isVoicePresent(const char *file) const { return false; } -int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { +int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) { Audio::SeekableAudioStream *audioStream = getVoiceStream(file); if (!audioStream) { @@ -81,7 +81,7 @@ int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volum } int playTime = audioStream->getLength().msecs(); - playVoiceStream(audioStream, handle, volume, isSfx); + playVoiceStream(audioStream, handle, volume, priority, isSfx); return playTime; } @@ -109,11 +109,19 @@ Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) const { } } -bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { +bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) { int h = 0; - while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h])) + while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle)) ++h; + if (h >= kNumChannelHandles) { + h = 0; + while (h < kNumChannelHandles && _soundChannels[h].priority > priority) + ++h; + if (h < kNumChannelHandles) + voiceStop(&_soundChannels[h].handle); + } + if (h >= kNumChannelHandles) { // When we run out of handles we need to destroy the stream object, // this is to avoid memory leaks in some scenes where too many sfx @@ -123,9 +131,10 @@ bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *hand return false; } - _mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h], stream, -1, volume); + _mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].handle, stream, -1, volume); + _soundChannels[h].priority = priority; if (handle) - *handle = _soundChannels[h]; + *handle = _soundChannels[h].handle; return true; } @@ -133,8 +142,8 @@ bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *hand void Sound::voiceStop(const Audio::SoundHandle *handle) { if (!handle) { for (int h = 0; h < kNumChannelHandles; ++h) { - if (_mixer->isSoundHandleActive(_soundChannels[h])) - _mixer->stopHandle(_soundChannels[h]); + if (_mixer->isSoundHandleActive(_soundChannels[h].handle)) + _mixer->stopHandle(_soundChannels[h].handle); } } else { _mixer->stopHandle(*handle); @@ -144,7 +153,7 @@ void Sound::voiceStop(const Audio::SoundHandle *handle) { bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const { if (!handle) { for (int h = 0; h < kNumChannelHandles; ++h) { - if (_mixer->isSoundHandleActive(_soundChannels[h])) + if (_mixer->isSoundHandleActive(_soundChannels[h].handle)) return true; } } else { @@ -156,7 +165,7 @@ bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const { bool Sound::allVoiceChannelsPlaying() const { for (int i = 0; i < kNumChannelHandles; ++i) - if (!_mixer->isSoundHandleActive(_soundChannels[i])) + if (!_mixer->isSoundHandleActive(_soundChannels[i].handle)) return false; return true; } diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 63cec48d00a8..384aeb4f35ce 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -184,11 +184,11 @@ class Sound { * @param handle store a copy of the sound handle * @return playtime of the voice file (-1 marks unknown playtime) */ - virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); + virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false); Audio::SeekableAudioStream *getVoiceStream(const char *file) const; - bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); + bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false); /** * Checks if a voice is being played. @@ -238,7 +238,13 @@ class Sound { kNumChannelHandles = 4 }; - Audio::SoundHandle _soundChannels[kNumChannelHandles]; + struct SoundChannel { + SoundChannel() : handle(), priority(0) {} + Audio::SoundHandle handle; + int priority; + }; + + SoundChannel _soundChannels[kNumChannelHandles]; int _musicEnabled; bool _sfxEnabled; diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index 827a48768511..e09fe7e36045 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -193,7 +193,7 @@ class SoundTownsPC98_v2 : public Sound { void haltTrack(); void beginFadeOut(); - int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx); + int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume = 255, uint8 priority = 255, bool isSfx = true); void playSoundEffect(uint8 track, uint8 volume = 0xff); void updateVolumeSettings(); diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index 6c88312f1ae0..3c2c93144570 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -165,9 +165,8 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { return; volume &= 0xff; - // Priority setting (used for acquiring one of the 4 pcm channels) currently not implemented. - // int16 vprIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); - // uint16 priority = (vprIndex > 0) ? (vprIndex * volume) >> 8 : -vprIndex; + int16 prIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); + uint16 priority = (prIndex > 0) ? (prIndex * volume) >> 8 : -prIndex; static const uint8 volTable1[] = { 223, 159, 95, 47, 15, 0 }; static const uint8 volTable2[] = { 255, 191, 127, 63, 30, 0 }; @@ -189,7 +188,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { if (hasVocFile) { if (_sound->isVoicePresent(_ingameSoundList[vocIndex])) - _sound->voicePlay(_ingameSoundList[vocIndex], 0, volume, true); + _sound->voicePlay(_ingameSoundList[vocIndex], 0, volume, priority, true); } else if (_flags.platform == Common::kPlatformPC) { if (_sound->getSfxType() == Sound::kMidiMT32) track = (track < _ingameMT32SoundIndexSize) ? (_ingameMT32SoundIndex[track] - 1) : -1; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 4b25db33f2bd..01624d510b02 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -569,15 +569,24 @@ void SoundTownsPC98_v2::beginFadeOut() { haltTrack(); } -int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8, bool) { +int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool) { static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; static const char patternHOF[] = "%s.PCM"; static const char patternLOL[] = "%s.VOC"; int h = 0; if (_currentSFX) { - while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h])) + while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle)) h++; + + if (h >= kNumChannelHandles) { + h = 0; + while (h < kNumChannelHandles && _soundChannels[h].priority > priority) + ++h; + if (h < kNumChannelHandles) + voiceStop(&_soundChannels[h].handle); + } + if (h >= kNumChannelHandles) return 0; } @@ -630,9 +639,10 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, } _currentSFX = Audio::makeRawStream(sfx, outsize, sfxRate * 10, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].handle, _currentSFX, -1, volume); + _soundChannels[h].priority = priority; if (handle) - *handle = _soundChannels[h]; + *handle = _soundChannels[h].handle; delete[] data; return 1;