diff options
-rw-r--r-- | engines/kyra/lol.cpp | 262 | ||||
-rw-r--r-- | engines/kyra/lol.h | 3 | ||||
-rw-r--r-- | engines/kyra/module.mk | 1 | ||||
-rw-r--r-- | engines/kyra/script_lol.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/script_tim.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/sound.cpp | 85 | ||||
-rw-r--r-- | engines/kyra/sound.h | 16 | ||||
-rw-r--r-- | engines/kyra/sound_lol.cpp | 317 | ||||
-rw-r--r-- | engines/kyra/sound_towns.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/text_lol.cpp | 2 |
10 files changed, 369 insertions, 331 deletions
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index da0703f5e0..02f3020ec0 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -412,6 +412,10 @@ LoLEngine::~LoLEngine() { for (Common::Array<const SpellProc*>::iterator i = _spellProcs.begin(); i != _spellProcs.end(); ++i) delete *i; _spellProcs.clear(); + + for (Common::List<Audio::AudioStream *>::iterator i = _speechList.begin(); i != _speechList.end(); ++i) + delete *i; + _speechList.clear(); } Screen *LoLEngine::screen() { @@ -896,7 +900,7 @@ void LoLEngine::update() { if (_gameFlags[15] & 0x4000 && !(_updateFlags & 4) && (_compassDirection == -1 || (_currentDirection << 6) != _compassDirection || _compassStep)) updateCompass(); - snd_characterSpeaking(); + snd_updateCharacterSpeech(); fadeText(); updateInput(); @@ -1096,7 +1100,7 @@ void LoLEngine::updatePortraitSpeechAnim() { f += 7; if (_speechFlag) { - if (snd_characterSpeaking() == 2) + if (snd_updateCharacterSpeech() == 2) _updatePortraitSpeechAnimDuration = 2; else _updatePortraitSpeechAnimDuration = 1; @@ -1670,260 +1674,6 @@ void LoLEngine::loadTalkFile(int index) { _res->loadPakFile(file); } -bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { - if (!_speechFlag) - return false; - - if (speaker < 65) { - if (_characters[speaker].flags & 1) - speaker = (int) _characters[speaker].name[0]; - else - speaker = 0; - } - - if (_lastSpeechId == id && speaker == _lastSpeaker) - return true; - - _lastSpeechId = id; - _lastSpeaker = speaker; - _nextSpeechId = _nextSpeaker = -1; - - Common::List<const char*> playList; - - char pattern1[8]; - char pattern2[5]; - char file1[13]; - char file2[13]; - char file3[13]; - file3[0] = 0; - - snprintf(pattern2, sizeof(pattern2), "%02d", id & 0x4000 ? 0 : _curTlkFile); - - if (id & 0x4000) { - snprintf(pattern1, sizeof(pattern1), "%03X", id & 0x3fff); - } else if (id < 1000) { - snprintf(pattern1, sizeof(pattern1), "%03d", id); - } else { - snprintf(file3, sizeof(file3), "@%04d%c.%s", id - 1000, (char)speaker, pattern2); - if (_res->exists(file3)) { - char *f = new char[strlen(file3) + 1]; - strcpy(f, file3); - playList.push_back(f); - } - } - - if (!file3[0]) { - for (char i = 0; ; i++) { - char symbol = '0' + i; - snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, symbol, pattern2); - snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', symbol, pattern2); - if (_res->exists(file1)) { - char *f = new char[strlen(file1) + 1]; - strcpy(f, file1); - playList.push_back(f); - } else if (_res->exists(file2)) { - char *f = new char[strlen(file2) + 1]; - strcpy(f, file2); - playList.push_back(f); - } else { - break; - } - } - } - - if (playList.empty()) - return false; - - while (_sound->voiceIsPlaying(_activeVoiceFile)) - delay(_tickLength, true, false); - - while (_sound->allVoiceChannelsPlaying()) - delay(_tickLength, false, true); - - strcpy(_activeVoiceFile, *playList.begin()); - _activeVoiceFileTotalTime = _sound->voicePlayFromList(playList); - - for (Common::List<const char*>::iterator i = playList.begin(); i != playList.end(); i++) - delete []*i; - playList.clear(); - - _tim->_abortFlag = 0; - - return true; -} - -int LoLEngine::snd_characterSpeaking() { - if (_sound->voiceIsPlaying(_activeVoiceFile)) - return 2; - - _lastSpeechId = _lastSpeaker = -1; - _activeVoiceFileTotalTime = 0; - - if (_nextSpeechId != -1) { - if (snd_playCharacterSpeech(_nextSpeechId, _nextSpeaker, 0)) - return 2; - } - - return 0; -} - -void LoLEngine::snd_stopSpeech(bool setFlag) { - if (!_sound->voiceIsPlaying(_activeVoiceFile)) - return; - - //_dlgTimer = 0; - _sound->voiceStop(_activeVoiceFile); - _activeVoiceFileTotalTime = 0; - _nextSpeechId = _nextSpeaker = -1; - - if (setFlag) - _tim->_abortFlag = 1; -} - -void LoLEngine::snd_playSoundEffect(int track, int volume) { - if (track == 1 && (_lastSfxTrack == -1 || _lastSfxTrack == 1)) - return; - - _lastSfxTrack = track; - if (track == -1) - return; - - int16 volIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); - - if (volIndex > 0) - volume = (volIndex * volume) >> 8; - else if (volIndex < 0) - volume = -volIndex; - - // volume TODO - volume = 254 - volume; - - int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); - - bool hasVocFile = false; - if (vocIndex != -1) { - if (scumm_stricmp(_ingameSoundList[vocIndex], "EMPTY")) - hasVocFile = true; - } - - if (hasVocFile) { - _sound->voicePlay(_ingameSoundList[vocIndex], volume & 0xff, true); - } else if (_flags.platform == Common::kPlatformPC) { - if (_sound->getSfxType() == Sound::kMidiMT32) - track = track < _ingameMT32SoundIndexSize ? _ingameMT32SoundIndex[track] - 1 : -1; - else if (_sound->getSfxType() == Sound::kMidiGM) - track = track < _ingameGMSoundIndexSize ? _ingameGMSoundIndex[track] - 1: -1; - - if (track == 168) - track = 167; - - if (track != -1) - KyraEngine_v1::snd_playSoundEffect(track, volume); - } -} - -void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) { - if (!_sound->sfxEnabled()) - return; - - if (_environmentSfx) - snd_playSoundEffect(_environmentSfx, _environmentSfxVol); - - int dist = 0; - if (block) { - dist = getMonsterDistance(_currentBlock, block); - if (dist > _envSfxDistThreshold) { - _environmentSfx = 0; - return; - } - } - - _environmentSfx = soundId; - _environmentSfxVol = (15 - ((block || dist < 2) ? dist : 0)) << 4; - - if (block != _currentBlock) { - static const int8 blockShiftTable[] = { -32, -31, 1, 33, 32, 31, -1, -33 }; - uint16 cbl = _currentBlock; - - for (int i = 3; i > 0; i--) { - int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5); - cbl += blockShiftTable[dir]; - if (cbl != block) { - if (testWallFlag(cbl, 0, 1)) - _environmentSfxVol >>= 1; - } - } - } - - if (!soundId || _sceneUpdateRequired) - return; - - snd_processEnvironmentalSoundEffect(0, 0); -} - -void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) { - if (_envSfxUseQueue && _envSfxNumTracksInQueue < 10) { - _envSfxQueuedTracks[_envSfxNumTracksInQueue] = soundId; - _envSfxQueuedBlocks[_envSfxNumTracksInQueue] = block; - _envSfxNumTracksInQueue++; - } else { - snd_processEnvironmentalSoundEffect(soundId, block); - } -} - -void LoLEngine::snd_playQueuedEffects() { - for (int i = 0; i < _envSfxNumTracksInQueue; i++) - snd_processEnvironmentalSoundEffect(_envSfxQueuedTracks[i], _envSfxQueuedBlocks[i]); - _envSfxNumTracksInQueue = 0; -} - -void LoLEngine::snd_loadSoundFile(int track) { - if (_sound->musicEnabled()) { - char filename[13]; - int t = (track - 250) * 3; - - if (_curMusicFileIndex != _musicTrackMap[t] || _curMusicFileExt != (char)_musicTrackMap[t + 1]) { - snd_stopMusic(); - snprintf(filename, sizeof(filename), "LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1]); - _sound->loadSoundFile(filename); - _curMusicFileIndex = _musicTrackMap[t]; - _curMusicFileExt = (char)_musicTrackMap[t + 1]; - } else { - snd_stopMusic(); - } - } else { - //XXX - } -} - -int LoLEngine::snd_playTrack(int track) { - if (track == -1) - return _lastMusicTrack; - - int res = _lastMusicTrack; - _lastMusicTrack = track; - - if (_sound->musicEnabled()) { - snd_loadSoundFile(track); - int t = (track - 250) * 3; - _sound->playTrack(_musicTrackMap[t + 2]); - } - - return res; -} - -int LoLEngine::snd_stopMusic() { - if (_sound->musicEnabled()) { - if (_sound->isPlaying()) { - _sound->beginFadeOut(); - _system->delayMillis(3 * _tickLength); - } - - _sound->haltTrack(); - } - return snd_playTrack(-1); -} - int LoLEngine::characterSays(int track, int charId, bool redraw) { if (charId == 1) { charId = _selectedCharacter; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 5a82a47cdb..19904fdbb2 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -413,7 +413,7 @@ private: void loadTalkFile(int index); void snd_playVoiceFile(int track) {} bool snd_playCharacterSpeech(int id, int8 speaker, int); - int snd_characterSpeaking(); + int snd_updateCharacterSpeech(); void snd_stopSpeech(bool setFlag); void snd_playSoundEffect(int track, int volume); void snd_processEnvironmentalSoundEffect(int soundId, int block); @@ -440,6 +440,7 @@ private: uint16 _envSfxQueuedBlocks[10]; int _nextSpeechId; int _nextSpeaker; + Common::List<Audio::AudioStream*> _speechList; int _curTlkFile; int _speechFlag; diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index ac28d741ca..eafc1f5436 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -56,6 +56,7 @@ MODULE_OBJS := \ sound_towns.o \ sound.o \ sound_lok.o \ + sound_lol.o \ sprites.o \ staticres.o \ text.o \ diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index a7b3d573b2..85ced707e6 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -1587,7 +1587,7 @@ int LoLEngine::olol_suspendMonster(EMCState *script) { int LoLEngine::olol_triggerEventOnMouseButtonClick(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_triggerEventOnMouseButtonClick(%p) (%d)", (const void *)script, stackPos(0)); gui_notifyButtonListChanged(); - snd_characterSpeaking(); + snd_updateCharacterSpeech(); int f = checkInput(0); removeInputTop(); @@ -1980,7 +1980,7 @@ int LoLEngine::olol_characterSays(EMCState *script) { if (stackPos(0) != -2) return characterSays(stackPos(0), stackPos(1), stackPos(2)); else - return snd_characterSpeaking(); + return snd_updateCharacterSpeech(); } int LoLEngine::olol_queueSpeech(EMCState *script) { diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 95276f58dd..80dca87763 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -1108,7 +1108,7 @@ uint16 TIMInterpreter_LoL::processDialogue() { } } - if (_vm->snd_characterSpeaking() != 2) { + if (_vm->snd_updateCharacterSpeech() != 2) { //if (_dlgTimer < _system->getMillis()) { res = 1; if (!_vm->shouldQuit()) { @@ -1201,7 +1201,7 @@ void TIMInterpreter_LoL::update() { void TIMInterpreter_LoL::checkSpeechProgress() { if (_vm->speechEnabled() && _currentTim->procParam > 1 && _currentTim->func[_currentFunc].loopIp) { - if (_vm->snd_characterSpeaking() != 2) { + if (_vm->snd_updateCharacterSpeech() != 2) { _currentTim->func[_currentFunc].loopIp = 0; _currentTim->dlgFunc = _currentFunc; advanceToOpcode(21); @@ -1235,7 +1235,7 @@ int TIMInterpreter_LoL::execCommand(int cmd, const uint16 *param) { int TIMInterpreter_LoL::cmd_setLoopIp(const uint16 *param) { if (_vm->speechEnabled()) { - if (_vm->snd_characterSpeaking() == 2) + if (_vm->snd_updateCharacterSpeech() == 2) _currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip; else advanceToOpcode(21); @@ -1253,7 +1253,7 @@ int TIMInterpreter_LoL::cmd_continueLoop(const uint16 *param) { func.ip = func.loopIp; - if (_vm->snd_characterSpeaking() != 2) { + if (_vm->snd_updateCharacterSpeech() != 2) { uint16 factor = param[0]; if (factor) { const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000); diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 5b32b69e19..975cff740a 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -66,17 +66,24 @@ bool Sound::voiceFileIsPresent(const char *file) { return false; } -int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { - char filenamebuffer[25]; +int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx, bool appendSuffix) { + int32 ptime = 0; + Audio::AudioStream *audioStream = getVoiceStream(file, &ptime, appendSuffix); - int h = 0; - while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) - h++; - if (h >= kNumChannelHandles) + if (!audioStream) { + warning("Couldn't load sound file '%s'", file); return 0; + } - Audio::AudioStream *audioStream = 0; + playVoiceStream(audioStream, file, volume, isSfx) ; + return ptime; +} + +Audio::AudioStream *Sound::getVoiceStream(const char *file, int32 *totalPlayingTime, bool appendSuffix) { + char filenamebuffer[25]; + + Audio::AudioStream *audioStream = 0; for (int i = 0; _supportedCodecs[i].fileext; ++i) { strcpy(filenamebuffer, file); strcat(filenamebuffer, _supportedCodecs[i].fileext); @@ -88,9 +95,12 @@ int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { break; } + int32 vocStreamPlayTime = 0; + if (!audioStream) { strcpy(filenamebuffer, file); - strcat(filenamebuffer, ".VOC"); + if (appendSuffix) + strcat(filenamebuffer, ".VOC"); uint32 fileSize = 0; byte *fileData = _vm->resource()->fileData(filenamebuffer, &fileSize); @@ -100,62 +110,25 @@ int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { Common::MemoryReadStream vocStream(fileData, fileSize); audioStream = Audio::makeVOCStream(vocStream, Audio::Mixer::FLAG_UNSIGNED); - delete[] fileData; - fileSize = 0; - } - - if (!audioStream) { - warning("Couldn't load sound file '%s'", file); - return 0; + if (audioStream) + vocStreamPlayTime = vocStream.size() * 1000 / audioStream->getRate(); + } else { + vocStreamPlayTime = audioStream->getTotalPlayTime(); } - - _soundChannels[h].file = file; - _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, audioStream, -1, volume); - - return audioStream->getTotalPlayTime(); + + *totalPlayingTime = vocStreamPlayTime; + return audioStream; } -uint32 Sound::voicePlayFromList(Common::List<const char*> fileList) { +void Sound::playVoiceStream(Audio::AudioStream *stream, const char *handleName, uint8 volume, bool isSfx) { int h = 0; while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return 0; - - Audio::AppendableAudioStream *out = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); - uint32 totalPlayTime = 0; - - for (Common::List<const char*>::iterator i = fileList.begin(); i != fileList.end(); i++) { - Common::SeekableReadStream *file = _vm->resource()->createReadStream(*i); - - if (!file) { - warning("Couldn't load voice file: %s", *i); - continue; - } - - int size, rate; - uint8 *data = Audio::loadVOCFromStream(*file, size, rate); - delete file; - - // FIXME/HACK: While loadVOCStream uses malloc / realloc, - // AppendableAudioStream uses delete[] to free the passed buffer. - // As a consequence we just 'move' the data to a buffer allocated - // via new[]. - uint8 *vocBuffer = new uint8[size]; - assert(vocBuffer); - memcpy(vocBuffer, data, size); - free(data); - - out->queueBuffer(vocBuffer, size); - totalPlayTime += size; - } - - totalPlayTime = (totalPlayTime * 1000) / 22050; - out->finish(); + return; - _soundChannels[h].file = *fileList.begin(); - _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, out); - return totalPlayTime; + _soundChannels[h].file = handleName; + _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, stream, -1, volume); } void Sound::voiceStop(const char *file) { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 52334806ad..bf121ede2b 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -195,15 +195,11 @@ public: * @param isSfx marks file as sfx instead of voice * @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, bool appendSuffix = true); + + Audio::AudioStream *getVoiceStream(const char *file, int32 *totalPlayingTime, bool appendSuffix = true); - /** - * Queues the specified voice files in an AppendableAudioStream - * and plays them. - * - * @param fileList: files to be played - */ - virtual uint32 voicePlayFromList(Common::List<const char*> fileList); + void playVoiceStream(Audio::AudioStream * stream, const char *handleName, uint8 volume = 255, bool isSfx = false); /** * Checks if a voice is being played. @@ -465,7 +461,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, bool appendSuffix = true) { return -1; } void playSoundEffect(uint8); protected: @@ -492,7 +488,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, bool appendSuffix = true); void playSoundEffect(uint8 track); protected: diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp new file mode 100644 index 0000000000..862788d524 --- /dev/null +++ b/engines/kyra/sound_lol.cpp @@ -0,0 +1,317 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/sound.h" +#include "kyra/lol.h" +#include "kyra/resource.h" + +namespace Kyra { + +bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { + if (!_speechFlag) + return false; + + if (speaker < 65) { + if (_characters[speaker].flags & 1) + speaker = (int) _characters[speaker].name[0]; + else + speaker = 0; + } + + if (_lastSpeechId == id && speaker == _lastSpeaker) + return true; + + _lastSpeechId = id; + _lastSpeaker = speaker; + _nextSpeechId = _nextSpeaker = -1; + + char pattern1[8]; + char pattern2[5]; + char file1[13]; + char file2[13]; + char file3[13]; + file3[0] = 0; + + Common::List<const char*> playList; + + snprintf(pattern2, sizeof(pattern2), "%02d", id & 0x4000 ? 0 : _curTlkFile); + + if (id & 0x4000) { + snprintf(pattern1, sizeof(pattern1), "%03X", id & 0x3fff); + } else if (id < 1000) { + snprintf(pattern1, sizeof(pattern1), "%03d", id); + } else { + snprintf(file3, sizeof(file3), "@%04d%c.%s", id - 1000, (char)speaker, pattern2); + if (_res->exists(file3)) { + char *f = new char[strlen(file3) + 1]; + strcpy(f, file3); + playList.push_back(f); + } + } + + if (!file3[0]) { + for (char i = 0; ; i++) { + char symbol = '0' + i; + snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, symbol, pattern2); + snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', symbol, pattern2); + if (_res->exists(file1)) { + char *f = new char[strlen(file1) + 1]; + strcpy(f, file1); + playList.push_back(f); + } else if (_res->exists(file2)) { + char *f = new char[strlen(file2) + 1]; + strcpy(f, file2); + playList.push_back(f); + } else { + break; + } + } + } + + if (playList.empty()) + return false; + + while (_sound->voiceIsPlaying(_activeVoiceFile)) + delay(_tickLength, true, false); + + while (_sound->allVoiceChannelsPlaying()) + delay(_tickLength, false, true); + + strcpy(_activeVoiceFile, *playList.begin()); + + _activeVoiceFileTotalTime = 0; + for (Common::List<Audio::AudioStream *>::iterator i = _speechList.begin(); i != _speechList.end(); ++i) + delete *i; + _speechList.clear(); + + int32 pt = 0; + for (Common::List<const char*>::iterator i = playList.begin(); i != playList.end(); ++i) { + Audio::AudioStream *a = _sound->getVoiceStream(*i, &pt, false); + _speechList.push_back(a); + _activeVoiceFileTotalTime += pt; + } + + //_activeVoiceFileTotalTime = _sound->voicePlay(_activeVoiceFile, 255, false, false); + _sound->playVoiceStream(*_speechList.begin(), _activeVoiceFile); + _speechList.pop_front(); + + playList.clear(); + //for (Common::List<const char*>::iterator i = _speechPlayList.begin(); i != _speechPlayList.end(); ++i) + // _activeVoiceFileTotalTime += _sound->getTotalPlayTime(*i, false); + /*if (_speechPlayList.begin() != _speechPlayList.end()) + _activeVoiceFileTotalTime |= 0x80000000;*/ + + if (!_activeVoiceFileTotalTime) + return false; + + _tim->_abortFlag = 0; + + return true; +} + +int LoLEngine::snd_updateCharacterSpeech() { + if (_sound->voiceIsPlaying(_activeVoiceFile)) + return 2; + + if (_speechList.begin() != _speechList.end()) { + _sound->playVoiceStream(*_speechList.begin(), _activeVoiceFile); + _speechList.pop_front(); + return 2; + + } else if (_nextSpeechId != -1) { + _lastSpeechId = _lastSpeaker = -1; + _activeVoiceFileTotalTime = 0; + if (snd_playCharacterSpeech(_nextSpeechId, _nextSpeaker, 0)) + return 2; + } + + _lastSpeechId = _lastSpeaker = -1; + _activeVoiceFileTotalTime = 0; + + return 0; +} + +void LoLEngine::snd_stopSpeech(bool setFlag) { + if (!_sound->voiceIsPlaying(_activeVoiceFile)) + return; + + //_dlgTimer = 0; + _sound->voiceStop(_activeVoiceFile); + _activeVoiceFileTotalTime = 0; + _nextSpeechId = _nextSpeaker = -1; + + for (Common::List<Audio::AudioStream *>::iterator i = _speechList.begin(); i != _speechList.end(); ++i) + delete *i; + _speechList.clear(); + + if (setFlag) + _tim->_abortFlag = 1; +} + +void LoLEngine::snd_playSoundEffect(int track, int volume) { + if (track == 1 && (_lastSfxTrack == -1 || _lastSfxTrack == 1)) + return; + + _lastSfxTrack = track; + if (track == -1) + return; + + int16 volIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); + + if (volIndex > 0) + volume = (volIndex * volume) >> 8; + else if (volIndex < 0) + volume = -volIndex; + + // volume TODO + volume = 254 - volume; + + int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); + + bool hasVocFile = false; + if (vocIndex != -1) { + if (scumm_stricmp(_ingameSoundList[vocIndex], "EMPTY")) + hasVocFile = true; + } + + if (hasVocFile) { + _sound->voicePlay(_ingameSoundList[vocIndex], volume & 0xff, true); + } else if (_flags.platform == Common::kPlatformPC) { + if (_sound->getSfxType() == Sound::kMidiMT32) + track = track < _ingameMT32SoundIndexSize ? _ingameMT32SoundIndex[track] - 1 : -1; + else if (_sound->getSfxType() == Sound::kMidiGM) + track = track < _ingameGMSoundIndexSize ? _ingameGMSoundIndex[track] - 1: -1; + + if (track == 168) + track = 167; + + if (track != -1) + KyraEngine_v1::snd_playSoundEffect(track, volume); + } +} + +void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) { + if (!_sound->sfxEnabled()) + return; + + if (_environmentSfx) + snd_playSoundEffect(_environmentSfx, _environmentSfxVol); + + int dist = 0; + if (block) { + dist = getMonsterDistance(_currentBlock, block); + if (dist > _envSfxDistThreshold) { + _environmentSfx = 0; + return; + } + } + + _environmentSfx = soundId; + _environmentSfxVol = (15 - ((block || dist < 2) ? dist : 0)) << 4; + + if (block != _currentBlock) { + static const int8 blockShiftTable[] = { -32, -31, 1, 33, 32, 31, -1, -33 }; + uint16 cbl = _currentBlock; + + for (int i = 3; i > 0; i--) { + int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5); + cbl += blockShiftTable[dir]; + if (cbl != block) { + if (testWallFlag(cbl, 0, 1)) + _environmentSfxVol >>= 1; + } + } + } + + if (!soundId || _sceneUpdateRequired) + return; + + snd_processEnvironmentalSoundEffect(0, 0); +} + +void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) { + if (_envSfxUseQueue && _envSfxNumTracksInQueue < 10) { + _envSfxQueuedTracks[_envSfxNumTracksInQueue] = soundId; + _envSfxQueuedBlocks[_envSfxNumTracksInQueue] = block; + _envSfxNumTracksInQueue++; + } else { + snd_processEnvironmentalSoundEffect(soundId, block); + } +} + +void LoLEngine::snd_playQueuedEffects() { + for (int i = 0; i < _envSfxNumTracksInQueue; i++) + snd_processEnvironmentalSoundEffect(_envSfxQueuedTracks[i], _envSfxQueuedBlocks[i]); + _envSfxNumTracksInQueue = 0; +} + +void LoLEngine::snd_loadSoundFile(int track) { + if (_sound->musicEnabled()) { + char filename[13]; + int t = (track - 250) * 3; + + if (_curMusicFileIndex != _musicTrackMap[t] || _curMusicFileExt != (char)_musicTrackMap[t + 1]) { + snd_stopMusic(); + snprintf(filename, sizeof(filename), "LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1]); + _sound->loadSoundFile(filename); + _curMusicFileIndex = _musicTrackMap[t]; + _curMusicFileExt = (char)_musicTrackMap[t + 1]; + } else { + snd_stopMusic(); + } + } else { + //XXX + } +} + +int LoLEngine::snd_playTrack(int track) { + if (track == -1) + return _lastMusicTrack; + + int res = _lastMusicTrack; + _lastMusicTrack = track; + + if (_sound->musicEnabled()) { + snd_loadSoundFile(track); + int t = (track - 250) * 3; + _sound->playTrack(_musicTrackMap[t + 2]); + } + + return res; +} + +int LoLEngine::snd_stopMusic() { + if (_sound->musicEnabled()) { + if (_sound->isPlaying()) { + _sound->beginFadeOut(); + _system->delayMillis(3 * _tickLength); + } + + _sound->haltTrack(); + } + return snd_playTrack(-1); +} + +} // end of namespace Kyra diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index f96e37b94f..2340f81aa8 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -4231,7 +4231,7 @@ void SoundTownsPC98_v2::beginFadeOut() { haltTrack(); } -int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) { +int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool, 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"; diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index 38b6078298..3e1ee84dec 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -640,7 +640,7 @@ void TextDisplayer_LoL::textPageBreak() { _vm->update(); if (_vm->_speechFlag) { - if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_characterSpeaking() != 2)) && speechPartTime) { + if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) { loop = false; inputFlag = 43; break; |