From 344caa88fcf8ce352e7bee6b2c6d4a8df2df548e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 24 May 2009 01:29:09 +0000 Subject: Make various Sound functionality SoundHandle instead of filename based. - This fixes multiple sounds being played at once in Lands of Lore svn-id: r40848 --- engines/kyra/kyra_hof.cpp | 4 +-- engines/kyra/kyra_v1.cpp | 1 - engines/kyra/kyra_v1.h | 4 ++- engines/kyra/script_lok.cpp | 2 +- engines/kyra/sequences_hof.cpp | 3 +- engines/kyra/sequences_lol.cpp | 28 +++++++-------- engines/kyra/sound.cpp | 81 +++++++++++++++--------------------------- engines/kyra/sound.h | 23 ++++++------ engines/kyra/sound_lok.cpp | 3 +- engines/kyra/sound_lol.cpp | 16 ++++----- engines/kyra/sound_towns.cpp | 9 ++--- 11 files changed, 72 insertions(+), 102 deletions(-) diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 40d4fb62f9..6057d3182a 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -1486,12 +1486,10 @@ void KyraEngine_HoF::snd_playVoiceFile(int id) { if (_sound->voiceFileIsPresent(vocFile)) { snd_stopVoice(); - while (!_sound->voicePlay(vocFile)) { + while (!_sound->voicePlay(vocFile, 255, false, &_speechHandle)) { updateWithText(); _system->delayMillis(10); } - - _speechFile = vocFile; } } diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 7e98c1be80..8585b0fced 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -52,7 +52,6 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) _gameSpeed = 60; _tickLength = (uint8)(1000.0 / _gameSpeed); - _speechFile = ""; _trackMap = 0; _trackMapSize = 0; _lastMusicCommand = -1; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 148da506c4..efa84bb488 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -32,6 +32,8 @@ #include "common/events.h" #include "common/system.h" +#include "sound/mixer.h" + #include "kyra/script.h" namespace Common { @@ -278,7 +280,7 @@ protected: uint8 _flagsTable[100]; // TODO: check this value // sound - Common::String _speechFile; + Audio::SoundHandle _speechHandle; int _curMusicTheme; int _curSfxFile; diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 6d8c27fadc..e6dbbd27b9 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -731,7 +731,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { voiceTime /= 100; if (voiceSync) { - uint32 voicePlayedTime = _sound->voicePlayedTime(_speechFile.c_str()); + uint32 voicePlayedTime = _sound->voicePlayedTime(_speechHandle); if (voicePlayedTime >= voiceTime) voiceTime = 0; else diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index a17579ee7c..0a9f37f94d 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -2149,8 +2149,7 @@ void KyraEngine_HoF::seq_playTalkText(uint8 chatNum) { if (chatNum < 12 && !_flags.isDemo && textEnabled()) seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160); - _speechFile = _sequenceSoundList[chatNum]; - _sound->voicePlay(_sequenceSoundList[chatNum]); + _sound->voicePlay(_sequenceSoundList[chatNum], 255, false, &_speechHandle); } void KyraEngine_HoF::seq_waitForTextsTimeout() { diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index 5df84958b4..bdcc3fd91d 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -367,10 +367,10 @@ void LoLEngine::kingSelectionIntro() { _screen->fprintStringIntro(_tim->getCTableEntry(60), 8, y + 30, 0x32, 0x00, 0x9C, 0x20); _screen->fprintStringIntro(_tim->getCTableEntry(61), 8, y + 40, 0x32, 0x00, 0x9C, 0x20); - _sound->voicePlay("KING01"); + _sound->voicePlay("KING01", 255, false, &_speechHandle); int index = 4; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING01"))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -396,7 +396,7 @@ void LoLEngine::kingSelectionIntro() { _chargenWSA->displayFrame(0x10, 0,113, 0, 0, 0, 0); _screen->updateScreen(); - _sound->voiceStop("KING01"); + _sound->voiceStop(&_speechHandle); } void LoLEngine::kingSelectionReminder() { @@ -406,10 +406,10 @@ void LoLEngine::kingSelectionReminder() { _screen->fprintStringIntro(_tim->getCTableEntry(62), 8, y, 0x32, 0x00, 0x9C, 0x20); _screen->fprintStringIntro(_tim->getCTableEntry(63), 8, y + 10, 0x32, 0x00, 0x9C, 0x20); - _sound->voicePlay("KING02"); + _sound->voicePlay("KING02", 255, false, &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING02"))) && _charSelection == -1 && !shouldQuit() && index < 15) { + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0); _screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); @@ -429,14 +429,14 @@ void LoLEngine::kingSelectionReminder() { break; } - _sound->voiceStop("KING02"); + _sound->voiceStop(&_speechHandle); } void LoLEngine::kingSelectionOutro() { - _sound->voicePlay("KING03"); + _sound->voicePlay("KING03", 255, false, &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying("KING03"))) && !shouldQuit() && !skipFlag()) { + while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -458,7 +458,7 @@ void LoLEngine::kingSelectionOutro() { _chargenWSA->displayFrame(0x10, 0, 113, 0, 0, 0, 0); _screen->updateScreen(); - _sound->voiceStop("KING03"); + _sound->voiceStop(&_speechHandle); } void LoLEngine::processCharacterSelection() { @@ -582,11 +582,11 @@ void LoLEngine::selectionCharInfoIntro(char *file) { file[4] = '0'; while (_charSelectionInfoResult == -1 && !shouldQuit()) { - if (!_sound->voicePlay(file)) + if (!_sound->voicePlay(file, 255, false, &_speechHandle)) break; int i = 0; - while (_sound->voiceIsPlaying(file) && _charSelectionInfoResult == -1 && !shouldQuit()) { + while (_sound->voiceIsPlaying(&_speechHandle) && _charSelectionInfoResult == -1 && !shouldQuit()) { _screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0); _screen->updateScreen(); @@ -599,7 +599,7 @@ void LoLEngine::selectionCharInfoIntro(char *file) { i = (i + 1) % 32; } - _sound->voiceStop(file); + _sound->voiceStop(&_speechHandle); file[4] = ++index + '0'; } @@ -664,8 +664,8 @@ void LoLEngine::showStarcraftLogo() { } if (!(shouldQuit() || inputFlag)) { - _sound->voicePlay("star2"); - while(_sound->voiceIsPlaying("star2") && !(shouldQuit() || inputFlag)) { + _sound->voicePlay("star2", 255, false, &_speechHandle); + while(_sound->voiceIsPlaying(&_speechHandle) && !(shouldQuit() || inputFlag)) { inputFlag = checkInput(0) & 0xff; delay(_tickLength); } diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index cd86d388d8..62eedae559 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -49,24 +49,17 @@ Sound::~Sound() { } bool Sound::voiceFileIsPresent(const char *file) { - char filenamebuffer[25]; for (int i = 0; _supportedCodecs[i].fileext; ++i) { - strcpy(filenamebuffer, file); - strcat(filenamebuffer, _supportedCodecs[i].fileext); - if (_vm->resource()->getFileSize(filenamebuffer) > 0) + Common::String f = file; + f += _supportedCodecs[i].fileext; + if (_vm->resource()->getFileSize(f.c_str()) > 0) return true; } - strcpy(filenamebuffer, file); - strcat(filenamebuffer, ".VOC"); - - if (_vm->resource()->getFileSize(filenamebuffer) > 0) - return true; - return false; } -int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { +int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx, Audio::SoundHandle *handle) { Audio::AudioStream *audioStream = getVoiceStream(file); if (!audioStream) { @@ -75,7 +68,7 @@ int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { } int playTime = audioStream->getTotalPlayTime(); - playVoiceStream(audioStream, file, volume, isSfx); + playVoiceStream(audioStream, handle, volume, isSfx); return playTime; } @@ -97,66 +90,51 @@ Audio::AudioStream *Sound::getVoiceStream(const char *file) { return audioStream; } -void Sound::playVoiceStream(Audio::AudioStream *stream, const char *handleName, uint8 volume, bool isSfx) { +bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { int h = 0; - while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) + while (_mixer->isSoundHandleActive(_soundChannels[h]) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return; + return false; + + _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h], stream, -1, volume); + if (handle) + *handle = _soundChannels[h]; - _soundChannels[h].file = handleName; - _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, stream, -1, volume); + return true; } -void Sound::voiceStop(const char *file) { - if (!file) { +void Sound::voiceStop(const Audio::SoundHandle *handle) { + if (!handle) { for (int h = 0; h < kNumChannelHandles; h++) { - if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle)) - _mixer->stopHandle(_soundChannels[h].channelHandle); + if (_mixer->isSoundHandleActive(_soundChannels[h])) + _mixer->stopHandle(_soundChannels[h]); } } else { - for (int i = 0; i < kNumChannelHandles; ++i) { - if (_soundChannels[i].file == file) - _mixer->stopHandle(_soundChannels[i].channelHandle); - } + _mixer->stopHandle(*handle); } } -bool Sound::voiceIsPlaying(const char *file) { - bool res = false; - if (!file) { +bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) { + if (!handle) { for (int h = 0; h < kNumChannelHandles; h++) { - if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle)) - res = true; + if (_mixer->isSoundHandleActive(_soundChannels[h])) + return true; } } else { - for (int i = 0; i < kNumChannelHandles; ++i) { - if (_soundChannels[i].file == file) - res = _mixer->isSoundHandleActive(_soundChannels[i].channelHandle); - } + return _mixer->isSoundHandleActive(*handle); } - return res; + + return false; } bool Sound::allVoiceChannelsPlaying() { for (int i = 0; i < kNumChannelHandles; ++i) - if (!_mixer->isSoundHandleActive(_soundChannels[i].channelHandle)) + if (!_mixer->isSoundHandleActive(_soundChannels[i])) return false; return true; } -uint32 Sound::voicePlayedTime(const char *file) { - if (!file) - return 0; - - for (int i = 0; i < kNumChannelHandles; ++i) { - if (_soundChannels[i].file == file) - return _mixer->getSoundElapsedTime(_soundChannels[i].channelHandle); - } - - return 0; -} - #pragma mark - void KyraEngine_v1::snd_playTheme(int file, int track) { @@ -224,14 +202,11 @@ void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) { } void KyraEngine_v1::snd_stopVoice() { - if (!_speechFile.empty()) { - _sound->voiceStop(_speechFile.c_str()); - _speechFile.clear(); - } + _sound->voiceStop(&_speechHandle); } bool KyraEngine_v1::snd_voiceIsPlaying() { - return _speechFile.empty() ? false : _sound->voiceIsPlaying(_speechFile.c_str()); + return _sound->voiceIsPlaying(&_speechHandle); } // static res diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 49a92c89f4..6501d267b9 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -190,20 +190,21 @@ public: * @param file file to be played * @param volume volume of the voice file * @param isSfx marks file as sfx instead of voice + * @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, uint8 volume = 255, bool isSfx = false); + virtual int32 voicePlay(const char *file, uint8 volume = 255, bool isSfx = false, Audio::SoundHandle *handle = 0); Audio::AudioStream *getVoiceStream(const char *file); - void playVoiceStream(Audio::AudioStream * stream, const char *handleName, uint8 volume = 255, bool isSfx = false); + bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); /** * Checks if a voice is being played. * * @return true when playing, else false */ - bool voiceIsPlaying(const char *file = 0); + bool voiceIsPlaying(const Audio::SoundHandle *handle = 0); /** * Checks if all voice handles are used. @@ -217,12 +218,14 @@ public: * * @return time in milliseconds */ - uint32 voicePlayedTime(const char *file); + uint32 voicePlayedTime(const Audio::SoundHandle &handle) { + return _mixer->getSoundElapsedTime(handle); + } /** * Stops playback of the current voice. */ - void voiceStop(const char *file = 0); + void voiceStop(const Audio::SoundHandle *handle = 0); protected: const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->fileListLen) ? _soundDataList->fileList[file] : ""; } int fileListLen() const { return _soundDataList->fileListLen; } @@ -234,11 +237,7 @@ protected: kNumChannelHandles = 4 }; - struct SoundChannel { - Common::String file; - Audio::SoundHandle channelHandle; - }; - SoundChannel _soundChannels[kNumChannelHandles]; + Audio::SoundHandle _soundChannels[kNumChannelHandles]; int _musicEnabled; bool _sfxEnabled; @@ -458,7 +457,7 @@ public: void haltTrack(); void beginFadeOut(); - int32 voicePlay(const char *file, uint8 volume = 255, bool isSfx = false) { return -1; } + int32 voicePlay(const char *file, uint8 volume = 255, bool isSfx = false, Audio::SoundHandle *handle = 0) { return -1; } void playSoundEffect(uint8); protected: @@ -485,7 +484,7 @@ public: void haltTrack(); void beginFadeOut(); - int32 voicePlay(const char *file, uint8 volume = 255, bool isSfx = false); + int32 voicePlay(const char *file, uint8 volume = 255, bool isSfx = false, Audio::SoundHandle *handle = 0); void playSoundEffect(uint8 track); protected: diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index 6645c57f32..38651e2779 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -72,8 +72,7 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { void KyraEngine_LoK::snd_playVoiceFile(int id) { char vocFile[9]; snprintf(vocFile, sizeof(vocFile), "%03d", id); - _speechFile = vocFile; - _speechPlayTime = _sound->voicePlay(vocFile); + _speechPlayTime = _sound->voicePlay(vocFile, 255, false, &_speechHandle); } void KyraEngine_LoK::snd_voiceWaitForFinish(bool ingame) { diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index 1f5b155b94..7afba2ae10 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -29,8 +29,6 @@ namespace Kyra { -#define LOL_VOICE_HANDLE "LoL_VOICE" - bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { if (!_speechFlag) return false; @@ -88,22 +86,22 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { if (newSpeechList.empty()) return false; - while (_sound->voiceIsPlaying(LOL_VOICE_HANDLE)) + while (_sound->voiceIsPlaying(&_speechHandle)) delay(_tickLength, true, false); while (_sound->allVoiceChannelsPlaying()) delay(_tickLength, false, true); - _activeVoiceFileTotalTime = 0; for (Common::List::iterator i = _speechList.begin(); i != _speechList.end(); ++i) delete *i; _speechList.clear(); _speechList = newSpeechList; + _activeVoiceFileTotalTime = 0; for (Common::List::const_iterator i = _speechList.begin(); i != _speechList.end(); ++i) _activeVoiceFileTotalTime += (*i)->getTotalPlayTime(); - _sound->playVoiceStream(*_speechList.begin(), LOL_VOICE_HANDLE); + _sound->playVoiceStream(*_speechList.begin(), &_speechHandle); _speechList.pop_front(); if (!_activeVoiceFileTotalTime) @@ -115,11 +113,11 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { } int LoLEngine::snd_updateCharacterSpeech() { - if (_sound->voiceIsPlaying(LOL_VOICE_HANDLE)) + if (_sound->voiceIsPlaying(&_speechHandle)) return 2; if (_speechList.begin() != _speechList.end()) { - _sound->playVoiceStream(*_speechList.begin(), LOL_VOICE_HANDLE); + _sound->playVoiceStream(*_speechList.begin(), &_speechHandle); _speechList.pop_front(); return 2; @@ -137,11 +135,11 @@ int LoLEngine::snd_updateCharacterSpeech() { } void LoLEngine::snd_stopSpeech(bool setFlag) { - if (!_sound->voiceIsPlaying(LOL_VOICE_HANDLE)) + if (!_sound->voiceIsPlaying(&_speechHandle)) return; //_dlgTimer = 0; - _sound->voiceStop(LOL_VOICE_HANDLE); + _sound->voiceStop(&_speechHandle); _activeVoiceFileTotalTime = 0; _nextSpeechId = _nextSpeaker = -1; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index f96e37b94f..3e39a1d131 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -4231,14 +4231,14 @@ void SoundTownsPC98_v2::beginFadeOut() { haltTrack(); } -int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) { +int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool, Audio::SoundHandle *handle) { 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 (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) + while (_mixer->isSoundHandleActive(_soundChannels[h]) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) return 0; @@ -4297,8 +4297,9 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) { _currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - _soundChannels[h].file = file; - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].channelHandle, _currentSFX); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX); + if (handle) + *handle = _soundChannels[h]; delete[] data; return 1; -- cgit v1.2.3