From a169619526c811f1718bbeb5ed980f68b9d2c8e7 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 21 Mar 2008 16:18:27 +0000 Subject: - Implemented opcode 97: o2_isAnySoundPlaying - reworked sound channel handling in HoF => fixed some voice related bugs svn-id: r31209 --- engines/kyra/kyra.cpp | 1 + engines/kyra/kyra.h | 8 +++++ engines/kyra/kyra_v2.cpp | 11 +++++- engines/kyra/kyra_v2.h | 7 +--- engines/kyra/script_v2.cpp | 7 +++- engines/kyra/sequences_v2.cpp | 3 +- engines/kyra/sound.cpp | 81 +++++++++++++++++++++++++++++++------------ engines/kyra/sound.h | 24 ++++++++----- engines/kyra/sound_towns.cpp | 4 +-- engines/kyra/sound_v1.cpp | 1 + 10 files changed, 104 insertions(+), 43 deletions(-) diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp index 6bb92f9566..b1af49a5ae 100644 --- a/engines/kyra/kyra.cpp +++ b/engines/kyra/kyra.cpp @@ -53,6 +53,7 @@ KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags) _quitFlag = false; + _speechFile = ""; _trackMap = 0; _trackMapSize = 0; _lastMusicCommand = -1; diff --git a/engines/kyra/kyra.h b/engines/kyra/kyra.h index 7207c63090..b024432b36 100644 --- a/engines/kyra/kyra.h +++ b/engines/kyra/kyra.h @@ -84,6 +84,12 @@ enum kDebugLevels { kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions }; +enum kMusicDataID { + kMusicIntro = 0, + kMusicIngame, + kMusicFinale +}; + class Screen; class Resource; class Sound; @@ -191,6 +197,8 @@ protected: uint8 _flagsTable[100]; // TODO: check this value // sound + Common::String _speechFile; + int _curMusicTheme; int _curSfxFile; int16 _lastMusicCommand; diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 4b242b0f32..927b7e5c3e 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -1708,6 +1708,7 @@ void KyraEngine_v2::restoreGfxRect32x32(int x, int y) { #pragma mark - void KyraEngine_v2::openTalkFile(int newFile) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::openTalkFile(%d)", newFile); char talkFilename[16]; if (_oldTalkFile > 0) { @@ -1732,10 +1733,17 @@ void KyraEngine_v2::snd_playVoiceFile(int id) { char vocFile[9]; assert(id >= 0 && id <= 9999999); sprintf(vocFile, "%07d", id); - _sound->voicePlay(vocFile); + if (_sound->voiceFileIsPresent(vocFile)) { + while (!_sound->voicePlay(vocFile)) { + updateWithText(); + _system->delayMillis(10); + } + _speechFile = vocFile; + } } void KyraEngine_v2::snd_loadSoundFile(int id) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::snd_loadSoundFile(%d)", id); if (id < 0 || !_trackMap) return; @@ -1746,6 +1754,7 @@ void KyraEngine_v2::snd_loadSoundFile(int id) { } void KyraEngine_v2::playVoice(int high, int low) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::playVoice(%d, %d)", high, low); if (!_flags.isTalkie) return; int vocFile = high * 10000 + low * 10; diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index cfd11a425d..ac6e5a3628 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -158,12 +158,6 @@ struct NestedSequence { uint16 finalCommand; }; -enum kMusicDataID { - kMusicIntro = 0, - kMusicIngame, - kMusicFinale -}; - class KyraEngine_v2 : public KyraEngine { friend class Debugger_v2; friend class TextDisplayer_v2; @@ -1036,6 +1030,7 @@ protected: int o2_setCauldronState(ScriptState *script); int o2_showItemString(ScriptState *script); int o2_getRand(ScriptState *script); + int o2_isAnySoundPlaying(ScriptState *script); int o2_setDeathHandlerFlag(ScriptState *script); int o2_setDrawNoShapeFlag(ScriptState *script); int o2_setRunFlag(ScriptState *script); diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp index 88350c3cc7..78b720d6e9 100644 --- a/engines/kyra/script_v2.cpp +++ b/engines/kyra/script_v2.cpp @@ -884,6 +884,11 @@ int KyraEngine_v2::o2_getRand(ScriptState *script) { return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); } +int KyraEngine_v2::o2_isAnySoundPlaying(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_isAnySoundPlaying(%p) ()", (const void *)script); + return _sound->voiceIsPlaying(); +} + int KyraEngine_v2::o2_setDeathHandlerFlag(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0)); _deathHandler = stackPos(0); @@ -1782,7 +1787,7 @@ void KyraEngine_v2::setupOpcodeTable() { Opcode(o2_showItemString), // 0x60 Opcode(o2_getRand), - OpcodeUnImpl(), + Opcode(o2_isAnySoundPlaying), Opcode(o2_setDeathHandlerFlag), Opcode(o2_setDrawNoShapeFlag), // 0x64 diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp index f0688d6e3d..41f98f8caf 100644 --- a/engines/kyra/sequences_v2.cpp +++ b/engines/kyra/sequences_v2.cpp @@ -1968,13 +1968,14 @@ void KyraEngine_v2::seq_cmpFadeFrame(const char *cmpFile) { } void KyraEngine_v2::seq_playTalkText(uint8 chatNum) { - debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playIntroChat(%i)", chatNum); + debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playTalkText(%i)", chatNum); assert(chatNum < _sequenceSoundListSize); if (chatNum < 12 && !_flags.isDemo && textEnabled()) seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160); + _speechFile = _sequenceSoundList[chatNum]; _sound->voicePlay(_sequenceSoundList[chatNum]); } diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 692db54af5..7dee4908fe 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -39,26 +39,44 @@ namespace Kyra { Sound::Sound(KyraEngine *vm, Audio::Mixer *mixer) - : _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandles(), - _musicEnabled(1), _sfxEnabled(true), _soundDataList(0) { + : _vm(vm), _mixer(mixer), _soundChannels(), _musicEnabled(1), + _sfxEnabled(true), _soundDataList(0) { } Sound::~Sound() { } -void Sound::voicePlay(const char *file) { +bool Sound::voiceFileIsPresent(const char *file) { + char filenamebuffer[25]; + for (int i = 0; _supportedCodes[i].fileext; ++i) { + strcpy(filenamebuffer, file); + strcat(filenamebuffer, _supportedCodes[i].fileext); + if (_vm->resource()->getFileSize(filenamebuffer) > 0) + return true; + } + + strcpy(filenamebuffer, file); + strcat(filenamebuffer, ".VOC"); + + if (_vm->resource()->getFileSize(filenamebuffer) > 0) + return true; + + return false; +} + +bool Sound::voicePlay(const char *file, bool isSfx) { uint32 fileSize = 0; byte *fileData = 0; bool found = false; char filenamebuffer[25]; int h = 0; - if (_currentVocFile) { - while (_mixer->isSoundHandleActive(_vocHandles[h])) - h++; - if (h >= kNumVocHandles) - return; - } + while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) + h++; + if (h >= kNumChannelHandles) + return false; + + Audio::AudioStream *audioStream = 0; for (int i = 0; _supportedCodes[i].fileext; ++i) { strcpy(filenamebuffer, file); @@ -67,7 +85,7 @@ void Sound::voicePlay(const char *file) { Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filenamebuffer); if (!stream) continue; - _currentVocFile = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1); + audioStream = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1); found = true; break; } @@ -78,30 +96,47 @@ void Sound::voicePlay(const char *file) { fileData = _vm->resource()->fileData(filenamebuffer, &fileSize); if (!fileData) - return; + return false; Common::MemoryReadStream vocStream(fileData, fileSize); - _currentVocFile = Audio::makeVOCStream(vocStream); + audioStream = Audio::makeVOCStream(vocStream); } - _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandles[h], _currentVocFile); + _soundChannels[h].file = file; + _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, audioStream); delete [] fileData; fileSize = 0; + + return true; } -void Sound::voiceStop() { - for (int h = 0; h < kNumVocHandles; h++) { - if (_mixer->isSoundHandleActive(_vocHandles[h])) - _mixer->stopHandle(_vocHandles[h]); +void Sound::voiceStop(const char *file) { + if (!file) { + for (int h = 0; h < kNumChannelHandles; h++) { + if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle)) + _mixer->stopHandle(_soundChannels[h].channelHandle); + } + } else { + for (int i = 0; i < kNumChannelHandles; ++i) { + if (_soundChannels[i].file == file) + _mixer->stopHandle(_soundChannels[i].channelHandle); + } } } -bool Sound::voiceIsPlaying() { +bool Sound::voiceIsPlaying(const char *file) { bool res = false; - for (int h = 0; h < kNumVocHandles; h++) { - if (_mixer->isSoundHandleActive(_vocHandles[h])) - res = true; + if (!file) { + for (int h = 0; h < kNumChannelHandles; h++) { + if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle)) + res = true; + } + } else { + for (int i = 0; i < kNumChannelHandles; ++i) { + if (_soundChannels[i].file == file) + res = true; + } } return res; } @@ -510,12 +545,12 @@ void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) { void KyraEngine::snd_stopVoice() { debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_stopVoice()"); - _sound->voiceStop(); + _sound->voiceStop(_speechFile.empty() ? 0 : _speechFile.c_str()); } bool KyraEngine::snd_voiceIsPlaying() { debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceIsPlaying()"); - return _sound->voiceIsPlaying(); + return _sound->voiceIsPlaying(_speechFile.empty() ? 0 : _speechFile.c_str()); } // static res diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 919cc3ceab..7c3bce38bc 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -52,7 +52,6 @@ #include "sound/softsynth/ym2612.h" #include "kyra/kyra.h" -#include "kyra/kyra_v2.h" namespace Audio { class AudioStream; @@ -149,6 +148,8 @@ public: void enableSFX(bool enable) { _sfxEnabled = enable; } bool sfxEnabled() const { return _sfxEnabled; } + virtual bool voiceFileIsPresent(const char *file); + /** * Plays the specified voice file. * @@ -160,28 +161,29 @@ public: * files * * @param file file to be played + * @param isSfx marks file as sfx instead of voice + * @return channel the voice file is played on */ - virtual void voicePlay(const char *file); + virtual bool voicePlay(const char *file, bool isSfx = false); /** * Checks if a voice is being played. * * @return true when playing, else false */ - bool voiceIsPlaying(); + bool voiceIsPlaying(const char *file = 0); /** * Stops playback of the current voice. */ - void voiceStop(); - + void voiceStop(const char *file = 0); protected: const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; } const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; } const int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; } enum { - kNumVocHandles = 4 + kNumChannelHandles = 4 }; int _musicEnabled; @@ -194,8 +196,12 @@ protected: private: const AudioDataStruct *_soundDataList; - Audio::AudioStream *_currentVocFile; - Audio::SoundHandle _vocHandles[kNumVocHandles]; + + struct SoundChannel { + Common::String file; + Audio::SoundHandle channelHandle; + }; + SoundChannel _soundChannels[kNumChannelHandles]; struct SpeechCodecs { const char *fileext; @@ -429,7 +435,7 @@ private: int _lastTrack; Audio::AudioStream *_currentSFX; - Audio::SoundHandle _sfxHandles[kNumVocHandles]; + Audio::SoundHandle _sfxHandles[kNumChannelHandles]; //SoundTowns_v2_TwnDriver *_driver; uint8 *_twnTrackData; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index e3102d747b..e34f7d014c 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1437,9 +1437,9 @@ void SoundTowns_v2::voicePlay(const char *file) { int h = 0; if (_currentSFX) { - while (_mixer->isSoundHandleActive(_sfxHandles[h])) + while (_mixer->isSoundHandleActive(_sfxHandles[h]) && h < kNumChannelHandles) h++; - if (h >= kNumVocHandles) + if (h >= kNumChannelHandles) return; } diff --git a/engines/kyra/sound_v1.cpp b/engines/kyra/sound_v1.cpp index 6c6d086882..9cb135983d 100644 --- a/engines/kyra/sound_v1.cpp +++ b/engines/kyra/sound_v1.cpp @@ -66,6 +66,7 @@ void KyraEngine_v1::snd_playVoiceFile(int id) { char vocFile[9]; assert(id >= 0 && id < 9999); sprintf(vocFile, "%03d", id); + _speechFile = vocFile; _sound->voicePlay(vocFile); } -- cgit v1.2.3