diff options
author | Paul Gilbert | 2016-08-06 12:14:02 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-08-06 12:14:02 -0400 |
commit | f0d208cdcf6e8fb8fc60ae3eddc62fc255fae2e4 (patch) | |
tree | 078f3b879d844b955b030d27b03918620c907421 /engines/titanic | |
parent | 139ad46410fe0a92a83eabd662caf2165eb498da (diff) | |
download | scummvm-rg350-f0d208cdcf6e8fb8fc60ae3eddc62fc255fae2e4.tar.gz scummvm-rg350-f0d208cdcf6e8fb8fc60ae3eddc62fc255fae2e4.tar.bz2 scummvm-rg350-f0d208cdcf6e8fb8fc60ae3eddc62fc255fae2e4.zip |
TITANIC: Added more sound manager methods
Diffstat (limited to 'engines/titanic')
-rw-r--r-- | engines/titanic/core/game_object.cpp | 4 | ||||
-rw-r--r-- | engines/titanic/core/game_object.h | 5 | ||||
-rw-r--r-- | engines/titanic/game/television.cpp | 8 | ||||
-rw-r--r-- | engines/titanic/pet_control/pet_conversations.cpp | 8 | ||||
-rw-r--r-- | engines/titanic/sound/qmixer.cpp | 28 | ||||
-rw-r--r-- | engines/titanic/sound/qmixer.h | 60 | ||||
-rw-r--r-- | engines/titanic/sound/sound.cpp | 8 | ||||
-rw-r--r-- | engines/titanic/sound/sound.h | 6 | ||||
-rw-r--r-- | engines/titanic/sound/sound_manager.cpp | 157 | ||||
-rw-r--r-- | engines/titanic/sound/sound_manager.h | 187 |
10 files changed, 392 insertions, 79 deletions
diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp index 30366398c1..d7556c76ff 100644 --- a/engines/titanic/core/game_object.cpp +++ b/engines/titanic/core/game_object.cpp @@ -425,11 +425,11 @@ void CGameObject::makeDirty() { makeDirty(_bounds); } -bool CGameObject::soundFn1(int handle) { +bool CGameObject::isSoundActive(int handle) const { if (handle != 0 && handle != -1) { CGameManager *gameManager = getGameManager(); if (gameManager) - return gameManager->_sound.fn1(handle); + return gameManager->_sound.isActive(handle); } return false; diff --git a/engines/titanic/core/game_object.h b/engines/titanic/core/game_object.h index ec7f77cff6..ecef68ce70 100644 --- a/engines/titanic/core/game_object.h +++ b/engines/titanic/core/game_object.h @@ -195,7 +195,10 @@ protected: */ void stopSound(int handle, int val2 = 0); - bool soundFn1(int handle); + /** + * Returns true if a sound with the specified handle is active + */ + bool isSoundActive(int handle) const; void soundFn2(const CString &resName, int v1, int v2, int v3, int handleIndex); diff --git a/engines/titanic/game/television.cpp b/engines/titanic/game/television.cpp index f5a7e5f63a..af6bdb8c03 100644 --- a/engines/titanic/game/television.cpp +++ b/engines/titanic/game/television.cpp @@ -103,7 +103,7 @@ void CTelevision::load(SimpleFile *file) { bool CTelevision::LeaveViewMsg(CLeaveViewMsg *msg) { petClear(); if (_isOn) { - if (soundFn1(_soundHandle)) + if (isSoundActive(_soundHandle)) stopSound(_soundHandle, 0); loadFrame(622); @@ -153,7 +153,7 @@ static const int END_FRAMES[8] = { 0, 55, 111, 167, 223, 279, 335, 391 }; bool CTelevision::PETUpMsg(CPETUpMsg *msg) { if (msg->_name == "Television" && _isOn) { - if (soundFn1(_soundHandle)) + if (isSoundActive(_soundHandle)) stopSound(_soundHandle, 0); _fieldE0 = _fieldE0 % _fieldE4 + 1; @@ -166,7 +166,7 @@ bool CTelevision::PETUpMsg(CPETUpMsg *msg) { bool CTelevision::PETDownMsg(CPETDownMsg *msg) { if (msg->_name == "Television" && _isOn) { - if (soundFn1(_soundHandle)) + if (isSoundActive(_soundHandle)) stopSound(_soundHandle, 0); if (--_fieldE0 < 1) _fieldE0 += _fieldE4; @@ -215,7 +215,7 @@ bool CTelevision::PETActivateMsg(CPETActivateMsg *msg) { _fieldE0 = 1; } else { stopMovie(); - if (soundFn1(_soundHandle)) + if (isSoundActive(_soundHandle)) stopSound(_soundHandle, 0); setVisible(false); diff --git a/engines/titanic/pet_control/pet_conversations.cpp b/engines/titanic/pet_control/pet_conversations.cpp index 9bae8e7070..dc096afcfe 100644 --- a/engines/titanic/pet_control/pet_conversations.cpp +++ b/engines/titanic/pet_control/pet_conversations.cpp @@ -541,14 +541,10 @@ void CPetConversations::npcDialChange(uint dialNum, int oldLevel, int newLevel) } int64 val1 = (oldLevel * dest) + (100 - oldLevel) * src; - val1 *= 0x51EB851F; - val1 >>= 37; - uint startFrame = val1 + (val1 >> 31); + uint startFrame = val1 / 100; int64 val2 = (newLevel * dest) + (100 - newLevel) * src; - val2 *= 0x51EB851F; - val2 >>= 37; - uint endFrame = val2 + (val2 >> 31); + uint endFrame = val2 / 100; if (startFrame != endFrame) _dials[dialNum].playMovie(startFrame, endFrame); diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp index d0117b240e..78b3755780 100644 --- a/engines/titanic/sound/qmixer.cpp +++ b/engines/titanic/sound/qmixer.cpp @@ -28,16 +28,16 @@ QMixer::QMixer(Audio::Mixer *mixer) : _mixer(mixer) { } bool QMixer::qsWaveMixInitEx(const QMIXCONFIG &config) { - // Not current implemented in ScummVM + // Not currently implemented in ScummVM return true; } void QMixer::qsWaveMixActivate(bool fActivate) { - // Not current implemented in ScummVM + // Not currently implemented in ScummVM } -int QMixer::qsWaveMixOpenChannel(int iChannel, WaveMixOpenChannel mode) { - // Not current implemented in ScummVM +int QMixer::qsWaveMixOpenChannel(int iChannel, QMixFlag mode) { + // Not currently implemented in ScummVM return 0; } @@ -49,4 +49,24 @@ void QMixer::qsWaveMixFreeWave(Audio::SoundHandle &handle) { _mixer->stopHandle(handle); } +void QMixer::qsWaveMixFlushChannel(int iChannel, uint flags) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetPanRate(int iChannel, uint flags, uint rate) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetVolume(int iChannel, uint flags, uint volume) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position) { + // Not currently implemented in ScummVM +} + } // End of namespace Titanic z diff --git a/engines/titanic/sound/qmixer.h b/engines/titanic/sound/qmixer.h index 8dda647d05..872a517cbc 100644 --- a/engines/titanic/sound/qmixer.h +++ b/engines/titanic/sound/qmixer.h @@ -27,11 +27,13 @@ namespace Titanic { -enum WaveMixOpenChannel { +enum QMixFlag { QMIX_OPENSINGLE = 0, // Open the single channel specified by iChannel QMIX_OPENALL = 1, // Opens all the channels, iChannel ignored QMIX_OPENCOUNT = 2, // Open iChannel Channels (eg. if iChannel = 4 will create channels 0-3) - QMIX_OPENAVAILABLE = 3 // Open the first unopened channel, and return channel number + QMIX_OPENAVAILABLE = 3, // Open the first unopened channel, and return channel number + + QMIX_USEONCE = 0x10 // settings are temporary }; /** @@ -63,6 +65,22 @@ struct QSVECTOR { double x; double y; double z; + + QSVECTOR() : x(0.0), y(0.0), z(0.0) {} + QSVECTOR(double xp, double yp, double zp) : x(xp), y(yp), z(zp) {} +}; + +/** + * Polar positioning + */ +struct QSPOLAR { + double azimuth; // degrees + double range; // meters + double elevation; // degrees + + QSPOLAR() : azimuth(0.0), range(0.0), elevation(0.0) {} + QSPOLAR(double azimuth_, double range_, double elevation_) : + azimuth(azimuth_), range(range_), elevation(elevation_) {} }; /** @@ -96,7 +114,7 @@ public: /** * Opens channels in the mixer for access */ - int qsWaveMixOpenChannel(int iChannel, WaveMixOpenChannel mode); + int qsWaveMixOpenChannel(int iChannel, QMixFlag mode); /** * Closes down the mixer @@ -107,6 +125,42 @@ public: * Stops a sound from playing */ void qsWaveMixFreeWave(Audio::SoundHandle &handle); + + /** + * Flushes a channel + */ + void qsWaveMixFlushChannel(int iChannel, uint flags = 0); + + /** + * Sets the amount of time, in milliseconds, to effect a change in + * a channel property (e.g. volume, position). Non-zero values + * smooth out changes + * @param iChannel Channel to change + * @param flags Flags + * @param rate Pan rate in milliseconds + */ + void qsWaveMixSetPanRate(int iChannel, uint flags, uint rate); + + /** + * Sets the volume for a channel + */ + void qsWaveMixSetVolume(int iChannel, uint flags, uint volume); + + /** + * Sets the relative position of a channel + * @param iChannel Channel number + * @param Flags Flags + * @param position Vector position for channel + */ + void qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position); + + /** + * Sets the relative position of a channel using polar co-ordinates + * @param iChannel Channel number + * @param Flags Flags + * @param position Polar position for channel + */ + void qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position); }; } // End of namespace Titanic diff --git a/engines/titanic/sound/sound.cpp b/engines/titanic/sound/sound.cpp index 5ee1d24d04..b796ba5595 100644 --- a/engines/titanic/sound/sound.cpp +++ b/engines/titanic/sound/sound.cpp @@ -55,11 +55,9 @@ void CSound::preEnterView(CViewItem *newView, bool isNewRoom) { warning("CSound::preEnterView"); } -bool CSound::fn1(int val) { - if (val == 0 || val == -1) { - if (!_soundManager.proc14()) - return true; - } +bool CSound::isActive(int handle) const { + if (handle != 0 && handle != -1) + return _soundManager.isActive(handle); return false; } diff --git a/engines/titanic/sound/sound.h b/engines/titanic/sound/sound.h index e2b5470458..bb2525a7c3 100644 --- a/engines/titanic/sound/sound.h +++ b/engines/titanic/sound/sound.h @@ -112,7 +112,11 @@ public: */ void preEnterView(CViewItem *newView, bool isNewRoom); - bool fn1(int val); + /** + * Returns true if a sound with the specified handle is active + */ + bool isActive(int handle) const; + void fn2(int handle); void fn3(int handle, int val2, int val3); void fn4(CWaveFile *waveFile, int val); diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp index ec26b170a6..17b53c2d92 100644 --- a/engines/titanic/sound/sound_manager.cpp +++ b/engines/titanic/sound/sound_manager.cpp @@ -21,7 +21,7 @@ */ #include "titanic/sound/sound_manager.h" - +#include "titanic/titanic.h" namespace Titanic { const uint SAMPLING_RATE = 22050; @@ -81,7 +81,9 @@ bool QSoundManagerSounds::contains(const CWaveFile *waveFile) const { QSoundManager::QSoundManager(Audio::Mixer *mixer) : CSoundManager(), QMixer(mixer), _field18(0), _field1C(0) { - Common::fill(&_field4A0[0], &_field4A0[16], 0); + _slots.resize(48); + Common::fill(&_channelsVolume[0], &_channelsVolume[16], 0); + Common::fill(&_channelsMode[0], &_channelsMode[16], 0); qsWaveMixInitEx(QMIXCONFIG(SAMPLING_RATE, CHANNELS_COUNT, LATENCY)); qsWaveMixActivate(true); @@ -120,7 +122,7 @@ int QSoundManager::playSound(CWaveFile &soundRes, CProximity &prox) { return 0; } -void QSoundManager::proc7() { +void QSoundManager::stopSound(uint handle) { warning("TODO"); } @@ -128,55 +130,97 @@ void QSoundManager::proc8(int v) { warning("TODO"); } -void QSoundManager::proc9() { - warning("TODO"); +void QSoundManager::proc9(uint handle) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._handle == handle) + _slots[idx]._val2 = 1; + } } -void QSoundManager::proc10() { - warning("TODO"); -} +void QSoundManager::stopAllChannels() { + qsWaveMixFlushChannel(0, QMIX_OPENALL); -void QSoundManager::proc11() { - warning("TODO"); + for (int idx = 0; idx < 16; ++idx) + _sounds.flushChannel(idx); + flushChannels(10); } -void QSoundManager::proc12() { - warning("TODO"); +void QSoundManager::setVolume(uint handle, uint volume, uint seconds) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + _channelsVolume[slot._channel] = volume; + updateVolume(slot._channel, seconds * 1000); + + if (volume) { + uint ticks = g_vm->_events->getTicksCount() + seconds * 1000; + if (!slot._ticks || ticks >= slot._ticks) + slot._ticks = ticks; + } else { + slot._ticks = 0; + } + break; + } + } } -void QSoundManager::proc13() { - warning("TODO"); +void QSoundManager::setVectorPosition(uint handle, double x, double y, double z, uint panRate) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate); + qsWaveMixSetSourcePosition(slot._channel, QMIX_USEONCE, QSVECTOR(x, y, z)); + break; + } + } } -bool QSoundManager::proc14() { - warning("TODO"); - return false; +void QSoundManager::setPolarPosition(uint handle, double range, double azimuth, double elevation, uint panRate) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate); + qsWaveMixSetPolarPosition(slot._channel, QMIX_USEONCE, + QSPOLAR(azimuth, range, elevation)); + break; + } + } } -bool QSoundManager::isActive(const CWaveFile *waveFile) const { - warning("TODO"); +bool QSoundManager::isActive(uint handle) const { + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._handle == handle) + return true; + } + return false; } -int QSoundManager::proc16() const { - warning("TODO"); - return 0; +bool QSoundManager::isActive(const CWaveFile *waveFile) const { + return _sounds.contains(waveFile); } uint QSoundManager::getLatency() const { return LATENCY; } -void QSoundManager::proc19(int v) { - warning("TODO"); +void QSoundManager::setMusicPercent(double percent) { + _musicPercent = percent; + updateVolumes(); } -void QSoundManager::proc20(int v) { - warning("TODO"); +void QSoundManager::setSpeechPercent(double percent) { + _speechPercent = percent; + updateVolumes(); } -void QSoundManager::proc21(int v) { - warning("TODO"); +void QSoundManager::setMasterPercent(double percent) { + _masterPercent = percent; + updateVolumes(); +} + +void QSoundManager::setParrotPercent(double percent) { + _parrotPercent = percent; } void QSoundManager::proc29() { @@ -191,4 +235,61 @@ void QSoundManager::soundFreed(Audio::SoundHandle &handle) { qsWaveMixFreeWave(handle); } +void QSoundManager::flushChannels(int channel) { + int endChannel; + switch (channel) { + case 0: + case 3: + endChannel = channel + 3; + break; + case 6: + endChannel = 10; + break; + case 10: + endChannel = 48; + break; + default: + return; + } + + for (; channel < endChannel; ++channel) { + qsWaveMixFlushChannel(channel); + _sounds.flushChannel(channel); + } +} + +void QSoundManager::updateVolume(int channel, uint panRate) { + uint volume = _channelsVolume[channel] * 327; + + switch (_channelsMode[channel]) { + case 0: + case 1: + case 2: + volume = (_speechPercent * volume) / 100; + break; + case 3: + case 4: + case 5: + volume = (24525 * volume) / 100; + break; + case 6: + case 7: + case 8: + case 9: + volume = (_masterPercent * volume) / 100; + break; + default: + break; + } + + volume = (_musicPercent * volume) / 100; + qsWaveMixSetPanRate(channel, 0, panRate); + qsWaveMixSetVolume(channel, 0, volume); +} + +void QSoundManager::updateVolumes() { + for (int idx = 0; idx < CHANNELS_COUNT; ++idx) + updateVolume(idx, 250); +} + } // End of namespace Titanic z diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h index e69cfffd78..b0591ce277 100644 --- a/engines/titanic/sound/sound_manager.h +++ b/engines/titanic/sound/sound_manager.h @@ -67,14 +67,51 @@ public: */ virtual int playSound(CWaveFile &waveFile, CProximity &prox) = 0; - virtual void proc7() = 0; + /** + * Stop playing the specified sound + */ + virtual void stopSound(uint handle) = 0; + virtual void proc8(int v) = 0; - virtual void proc9() {} - virtual void proc10() = 0; - virtual void proc11() = 0; - virtual void proc12() {} - virtual void proc13() {} - virtual bool proc14() = 0; + virtual void proc9(uint handle) {} + + /** + * Stops sounds on all playing channels + */ + virtual void stopAllChannels() = 0; + + /** + * Sets the volume for a sound + * @param handle Handle for sound + * @param volume New volume + * @param seconds Number of seconds to transition to the new volume + */ + virtual void setVolume(uint handle, uint volume, uint seconds) = 0; + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param x x position in metres + * @param y y position in metres + * @param z z position in metres + * @param panRate Rate in milliseconds to transition + */ + virtual void setVectorPosition(uint handle, double x, double y, double z, uint panRate) {} + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param range Range value in metres + * @param azimuth Azimuth value in degrees + * @param elevation Elevation value in degrees + * @param panRate Rate in milliseconds to transition + */ + virtual void setPolarPosition(uint handle, double range, double azimuth, double elevation, uint panRate) {} + + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(uint handle) const = 0; /** * Returns true if the given sound is currently active @@ -88,15 +125,30 @@ public: */ virtual uint getLatency() const { return 0; } - virtual void setMusicPercent(double percent) { _musicPercent = percent; } - virtual void setSpeechPercent(double percent) { _speechPercent = percent; } - virtual void setMasterPercent(double percent) { _masterPercent = percent; } - virtual void setParrotPercent(double percent) { _parrotPercent = percent; } + /** + * Sets the music volume percent + */ + virtual void setMusicPercent(double percent) = 0; + + /** + * Sets the speech volume percent + */ + virtual void setSpeechPercent(double percent) = 0; + + /** + * Sets the master volume percent + */ + virtual void setMasterPercent(double percent) = 0; + + /** + * Sets the Parrot NPC volume percent + */ + virtual void setParrotPercent(double percent) = 0; /** * Called when a game is about to be loaded */ - virtual void preLoad() { proc10(); } + virtual void preLoad() { stopAllChannels(); } /** * Load the data for the class from file @@ -124,6 +176,11 @@ public: virtual void postSave() {} virtual void proc29() {} + + /** + * Returns the parrot volume percent + */ + int getParrotVolume() const { return _parrotPercent; } }; class QSoundManagerSound : public ListItem { @@ -167,13 +224,40 @@ public: * the QMixer sound mixer class */ class QSoundManager : public CSoundManager, public QMixer { + struct Slot { + uint _val1; + uint _val2; + uint _ticks; + int _channel; + uint _handle; + Slot() : _val1(0), _val2(0), _ticks(0), _channel(0), _handle(0) {} + }; private: QSoundManagerSounds _sounds; + Common::Array<Slot> _slots; + uint _channelsVolume[16]; + int _channelsMode[16]; +private: + /** + * Flushes designated channels + */ + void flushChannels(int channel); + + /** + * Updates the volume for a channel + * @param channel Channel to be update + * @param panRate Time in milliseconds for change to occur + */ + void updateVolume(int channel, uint panRate); + + /** + * Updates all the volumes + */ + void updateVolumes(); public: int _field18; int _field1C; - int _field4A0[16]; public: QSoundManager(Audio::Mixer *mixer); virtual ~QSoundManager(); @@ -199,30 +283,83 @@ public: */ virtual int playSound(CWaveFile &waveFile, CProximity &prox); - virtual void proc7(); + /** + * Stop playing the specified sound + */ + virtual void stopSound(uint handle); + virtual void proc8(int v); - virtual void proc9(); - virtual void proc10(); - virtual void proc11(); - virtual void proc12(); - virtual void proc13(); - virtual bool proc14(); + virtual void proc9(uint handle); + + /** + * Stops sounds on all playing channels + */ + virtual void stopAllChannels(); + + /** + * Sets the volume for a sound + * @param handle Handle for sound + * @param volume New volume + * @param seconds Number of seconds to transition to the new volume + */ + virtual void setVolume(uint handle, uint volume, uint seconds); + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param x x position in metres + * @param y y position in metres + * @param z z position in metres + * @param panRate Rate in milliseconds to transition + */ + virtual void setVectorPosition(uint handle, double x, double y, double z, uint panRate); + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param range Range value in metres + * @param azimuth Azimuth value in degrees + * @param elevation Elevation value in degrees + * @param panRate Rate in milliseconds to transition + */ + virtual void setPolarPosition(uint handle, double range, double azimuth, double elevation, uint panRate); /** * Returns true if the given sound is currently active */ - virtual bool isActive(const CWaveFile *soundRes) const; + virtual bool isActive(uint handle) const; - virtual int proc16() const; + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(const CWaveFile *waveFile) const; + + virtual int proc16() const { return 1; } /** * Returns the movie latency */ virtual uint getLatency() const; - virtual void proc19(int v); - virtual void proc20(int v); - virtual void proc21(int v); + /** + * Sets the music volume percent + */ + virtual void setMusicPercent(double percent); + + /** + * Sets the speech volume percent + */ + virtual void setSpeechPercent(double percent); + + /** + * Sets the master volume percent + */ + virtual void setMasterPercent(double percent); + + /** + * Sets the Parrot NPC volume percent + */ + virtual void setParrotPercent(double percent); virtual void proc29(); virtual void proc30(); |