diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp index 6cd9db705650..73e3511319b0 100644 --- a/engines/titanic/core/game_object.cpp +++ b/engines/titanic/core/game_object.cpp @@ -437,8 +437,53 @@ bool CGameObject::isSoundActive(int handle) const { return false; } -void CGameObject::soundFn2(const CString &resName, int v1, int v2, int v3, int handleIndex) { - warning("TODO: CGameObject::soundFn2"); +void CGameObject::playGlobalSound(const CString &resName, int mode, bool initialMute, bool repeated, int handleIndex) { + if (handleIndex < 0 || handleIndex > 3) + return; + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + + // Preload the file, and stop any existing sound using the given slot + CSound &sound = gameManager->_sound; + g_vm->_filesManager->preload(resName); + if (_soundHandles[handleIndex] != -1) { + sound.stopSound(_soundHandles[handleIndex]); + _soundHandles[handleIndex] = -1; + } + + // If no new name specified, then exit + if (resName.empty()) + return; + + uint newVolume = sound._soundManager.getModeVolume(mode); + uint volume = initialMute ? 0 : newVolume; + + CProximity prox; + prox._channelVolume = newVolume; + prox._repeated = repeated; + + switch (handleIndex) { + case 0: + prox._channel = 6; + break; + case 1: + prox._channel = 7; + break; + case 2: + prox._channel = 8; + break; + case 3: + prox._channel = 9; + break; + default: + break; + } + + _soundHandles[handleIndex] = sound.playSound(resName, prox); + + if (_soundHandles[handleIndex]) + sound.setVolume(_soundHandles[handleIndex], newVolume, 2); } void CGameObject::setSoundVolume(uint handle, uint percent, uint seconds) { @@ -449,12 +494,47 @@ void CGameObject::setSoundVolume(uint handle, uint percent, uint seconds) { } } -void CGameObject::soundFn4(int v1, int v2, int v3) { +void CGameObject::stopGlobalSound(bool transition, int handleIndex) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + CSound &sound = gameManager->_sound; + + if (handleIndex == -1) { + for (int idx = 0; idx < 3; ++idx) { + if (_soundHandles[idx] != -1) { + sound.setVolume(_soundHandles[idx], 0, transition ? 1 : 0); + sound.setCanFree(_soundHandles[idx]); + _soundHandles[idx] = -1; + } + } + } else if (handleIndex >= 0 && handleIndex <= 2 && _soundHandles[handleIndex] != -1) { + if (transition) { + // Transitioning to silent over 1 second + sound.setVolume(_soundHandles[handleIndex], 0, 1); + sleep(1000); + } + + sound.stopSound(_soundHandles[handleIndex]); + _soundHandles[handleIndex] = -1; + } warning("CGameObject::soundFn4"); } -void CGameObject::soundFn5(int v1, int v2, int v3) { - warning("CGameObject::soundFn5"); +void CGameObject::setGlobalSoundVolume(int mode, uint seconds, int handleIndex) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + CSound &sound = gameManager->_sound; + + if (handleIndex == -1) { + // Iterate through calling the method for each handle + for (int idx = 0; idx < 3; ++idx) + setGlobalSoundVolume(mode, seconds, idx); + } else if (handleIndex >= 0 && handleIndex <= 2 && _soundHandles[handleIndex] != -1) { + uint newVolume = sound._soundManager.getModeVolume(mode); + sound.setVolume(_soundHandles[handleIndex], newVolume, seconds); + } } void CGameObject::sound8(bool flag) const { diff --git a/engines/titanic/core/game_object.h b/engines/titanic/core/game_object.h index 7bc5d156fc85..fdbbcd69595c 100644 --- a/engines/titanic/core/game_object.h +++ b/engines/titanic/core/game_object.h @@ -183,11 +183,15 @@ class CGameObject : public CNamedItem { /** * Plays a sound + * @param resName Filename of sound to play + * @param volume Volume level */ int playSound(const CString &name, uint volume = 100, int val3 = 0, bool repeated = false); /** * Plays a sound + * @param resName Filename of sound to play + * @param prox Proximity object with the sound data */ int playSound(const CString &name, CProximity &prox); @@ -203,8 +207,6 @@ class CGameObject : public CNamedItem { */ bool isSoundActive(int handle) const; - void soundFn2(const CString &resName, int v1, int v2, int v3, int handleIndex); - /** * Sets the volume for a sound * @param handle Sound handle @@ -213,9 +215,30 @@ class CGameObject : public CNamedItem { */ void setSoundVolume(uint handle, uint percent, uint seconds); - void soundFn4(int v1, int v2, int v3); + /** + * Plays a sound, and saves it's handle in the global sound handles list + * @param resName Filename of sound to play + * @param mode Volume mode level + * @param initialMute If set, sound transitions in from mute over 2 seconds + * @param repeated Flag for repeating sounds + * @param handleIndex Slot 0 to 3 in the shared sound handle list to store the sound's handle + */ + void playGlobalSound(const CString &resName, int mode, bool initialMute, bool repeated, int handleIndex); + + /** + * Stops a sound saved in the global sound handle list + * @param transition If set, the sound transitions to silent before stopping + * @param handleIndex Index of sound to stop. If -1, all global sounds are stopped + */ + void stopGlobalSound(bool transition, int handleIndex); - void soundFn5(int v1, int v2, int v3); + /** + * Updates the volume for a global sound based on the specified mode's volume + * @param mode Volume level mode + * @param seconds Number of seconds to transition to new volume + * @param handleIndex Index of global sound to update. If -1, all global sounds are updated + */ + void setGlobalSoundVolume(int mode, uint seconds, int handleIndex); void sound8(bool flag) const; diff --git a/engines/titanic/events.cpp b/engines/titanic/events.cpp index 997dbfa556d2..8a7cd550e8c9 100644 --- a/engines/titanic/events.cpp +++ b/engines/titanic/events.cpp @@ -114,9 +114,11 @@ uint32 Events::getTicksCount() const { void Events::sleep(uint time) { uint32 delayEnd = g_system->getMillis() + time; + CSound &sound = g_vm->_window->_gameManager->_sound; while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { pollEventsAndWait(); + sound.updateMixer(); } } diff --git a/engines/titanic/sound/sound.cpp b/engines/titanic/sound/sound.cpp index e499bd5b784c..9b894e5ecae4 100644 --- a/engines/titanic/sound/sound.cpp +++ b/engines/titanic/sound/sound.cpp @@ -204,4 +204,8 @@ void CSound::setCanFree(int handle) { _soundManager.setCanFree(handle); } +void CSound::updateMixer() { + _soundManager.waveMixPump(); +} + } // End of namespace Titanic diff --git a/engines/titanic/sound/sound.h b/engines/titanic/sound/sound.h index 34ef234f2a5c..d11839be0f3a 100644 --- a/engines/titanic/sound/sound.h +++ b/engines/titanic/sound/sound.h @@ -177,6 +177,11 @@ class CSound { * Flags that a sound can be freed if a timeout is set */ void setCanFree(int handle); + + /** + * Handles regularly updating the mixer + */ + void updateMixer(); }; } // End of namespace Titanic diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp index 2b5e137a5a98..7a188524adfa 100644 --- a/engines/titanic/sound/sound_manager.cpp +++ b/engines/titanic/sound/sound_manager.cpp @@ -32,6 +32,19 @@ CSoundManager::CSoundManager() : _musicPercent(75.0), _speechPercent(75.0), _masterPercent(75.0), _parrotPercent(75.0), _handleCtr(1) { } +uint CSoundManager::getModeVolume(int mode) { + switch (mode) { + case -1: + return _masterPercent; + case -2: + return _masterPercent * 30 / 100; + case -3: + return _masterPercent * 15 / 100; + default: + return 0; + } +} + /*------------------------------------------------------------------------*/ void QSoundManagerSounds::add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) { diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h index 91e11671950b..466607a1d50c 100644 --- a/engines/titanic/sound/sound_manager.h +++ b/engines/titanic/sound/sound_manager.h @@ -202,6 +202,11 @@ class CSoundManager { * Returns the parrot volume percent */ int getParrotVolume() const { return _parrotPercent; } + + /** + * Gets the volume for a given mode? value + */ + uint getModeVolume(int mode); }; class QSoundManagerSound : public ListItem {