diff options
Diffstat (limited to 'engines/titanic/sound')
-rw-r--r-- | engines/titanic/sound/qmixer.cpp | 59 | ||||
-rw-r--r-- | engines/titanic/sound/qmixer.h | 14 | ||||
-rw-r--r-- | engines/titanic/sound/sound.cpp | 3 | ||||
-rw-r--r-- | engines/titanic/sound/sound.h | 2 | ||||
-rw-r--r-- | engines/titanic/sound/sound_manager.cpp | 6 | ||||
-rw-r--r-- | engines/titanic/sound/sound_manager.h | 8 | ||||
-rw-r--r-- | engines/titanic/sound/wave_file.cpp | 10 | ||||
-rw-r--r-- | engines/titanic/sound/wave_file.h | 5 |
8 files changed, 88 insertions, 19 deletions
diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp index 733164947e..b3910f846a 100644 --- a/engines/titanic/sound/qmixer.cpp +++ b/engines/titanic/sound/qmixer.cpp @@ -60,7 +60,19 @@ void QMixer::qsWaveMixFreeWave(Audio::SoundHandle &handle) { } void QMixer::qsWaveMixFlushChannel(int iChannel, uint flags) { - // Not currently implemented in ScummVM + if (flags & QMIX_OPENALL) { + // Ignore channel, and flush all the channels + for (uint idx = 0; idx < _channels.size(); ++idx) + qsWaveMixFlushChannel(idx, 0); + } else { + // Flush the specified channel + Common::List<SoundEntry>::iterator i; + Common::List<SoundEntry> &sounds = _channels[iChannel]._sounds; + for (i = sounds.begin(); i != sounds.end(); ++i) + _mixer->stopHandle((*i)._soundHandle); + + sounds.clear(); + } } void QMixer::qsWaveMixSetPanRate(int iChannel, uint flags, uint rate) { @@ -83,11 +95,28 @@ void QMixer::qsWaveMixSetVolume(int iChannel, uint flags, uint volume) { } void QMixer::qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position) { - // Not currently implemented in ScummVM + ChannelEntry &channel = _channels[iChannel]; + + // Flag whether distance should reset when a new sound is started + channel._resetDistance = (flags & QMIX_USEONCE) != 0; + + // Currently, we only do a basic simulation of spatial positioning by + // getting the distance, and proportionately reducing the volume the + // further away the source is + channel._distance = sqrt(position.x * position.x + position.y * position.y + + position.z * position.z); } void QMixer::qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position) { - // Not currently implemented in ScummVM + ChannelEntry &channel = _channels[iChannel]; + + // Flag whether distance should reset when a new sound is started + channel._resetDistance = (flags & QMIX_USEONCE) != 0; + + // Currently, we only do a basic simulation of spatial positioning by + // getting the distance, and proportionately reducing the volume the + // further away the source is + channel._distance = position.range; } void QMixer::qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags) { @@ -163,7 +192,8 @@ void QMixer::qsWaveMixPump() { if (channel._volume != oldVolume && !channel._sounds.empty() && channel._sounds.front()._started) { - _mixer->setChannelVolume(channel._sounds.front()._soundHandle, channel._volume); + _mixer->setChannelVolume(channel._sounds.front()._soundHandle, + channel.getRawVolume()); } } @@ -177,7 +207,7 @@ void QMixer::qsWaveMixPump() { sound._waveFile->_stream->rewind(); _mixer->playStream(sound._waveFile->_soundType, &sound._soundHandle, sound._waveFile->_stream, - -1, channel._volume, 0, DisposeAfterUse::NO); + -1, channel.getRawVolume(), 0, DisposeAfterUse::NO); } else { // Sound is finished if (sound._callback) @@ -195,13 +225,30 @@ void QMixer::qsWaveMixPump() { if (!channel._sounds.empty()) { SoundEntry &sound = channel._sounds.front(); if (!sound._started) { + if (channel._resetDistance) + channel._distance = 0.0; + + // Calculate an effective volume based on distance of source _mixer->playStream(sound._waveFile->_soundType, &sound._soundHandle, sound._waveFile->_stream, - -1, channel._volume, 0, DisposeAfterUse::NO); + -1, channel.getRawVolume(), 0, DisposeAfterUse::NO); sound._started = true; } } } } +/*------------------------------------------------------------------------*/ + +byte QMixer::ChannelEntry::getRawVolume() const { + // Emperically decided adjustment divisor for distances + const double ADJUSTMENT_FACTOR = 5.0; + + double r = 1.0 + (_distance / ADJUSTMENT_FACTOR); + double percent = 1.0 / (r * r); + + double newVolume = _volume * percent; + return (byte)newVolume; +} + } // End of namespace Titanic diff --git a/engines/titanic/sound/qmixer.h b/engines/titanic/sound/qmixer.h index 9a0ea85ede..b8c7f6dae2 100644 --- a/engines/titanic/sound/qmixer.h +++ b/engines/titanic/sound/qmixer.h @@ -197,9 +197,19 @@ class QMixer { uint _volumeChangeEnd; byte _volumeStart; byte _volumeEnd; + // Distance of source + double _distance; + bool _resetDistance; ChannelEntry() : _volume(0), _panRate(0), _volumeChangeStart(0), - _volumeChangeEnd(0), _volumeStart(0), _volumeEnd(0) {} + _volumeChangeEnd(0), _volumeStart(0), _volumeEnd(0), + _distance(0.0), _resetDistance(true) {} + + /** + * Calculates the raw volume level to pass to ScummVM playStream, taking + * into the sound's volume level and distance from origin + */ + byte getRawVolume() const; }; private: Audio::Mixer *_mixer; @@ -290,7 +300,7 @@ public: void qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances); /** - * + * Sets the frequency/rate of sound playback */ void qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency); diff --git a/engines/titanic/sound/sound.cpp b/engines/titanic/sound/sound.cpp index e48c8760c5..c28823148e 100644 --- a/engines/titanic/sound/sound.cpp +++ b/engines/titanic/sound/sound.cpp @@ -57,7 +57,7 @@ void CSound::preEnterView(CViewItem *newView, bool isNewRoom) { _soundManager.setListenerPosition(xp, yp, zp, cosVal, sinVal, 0, isNewRoom); } -bool CSound::isActive(int handle) const { +bool CSound::isActive(int handle) { if (handle != 0 && handle != -1) return _soundManager.isActive(handle); @@ -129,6 +129,7 @@ CWaveFile *CSound::loadSound(const CString &name) { // Found it, so move it to the front of the list and return _sounds.remove(soundItem); _sounds.push_front(soundItem); + soundItem->_waveFile->reset(); return soundItem->_waveFile; } } diff --git a/engines/titanic/sound/sound.h b/engines/titanic/sound/sound.h index 21f2a93f24..c767a3d75f 100644 --- a/engines/titanic/sound/sound.h +++ b/engines/titanic/sound/sound.h @@ -115,7 +115,7 @@ public: /** * Returns true if a sound with the specified handle is active */ - bool isActive(int handle) const; + bool isActive(int handle); /** * Sets the volume for a sound diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp index c1a46e5103..5f8e53caf3 100644 --- a/engines/titanic/sound/sound_manager.cpp +++ b/engines/titanic/sound/sound_manager.cpp @@ -311,7 +311,9 @@ void QSoundManager::setPolarPosition(int handle, double range, double azimuth, d } } -bool QSoundManager::isActive(int handle) const { +bool QSoundManager::isActive(int handle) { + resetChannel(10); + for (uint idx = 0; idx < _slots.size(); ++idx) { if (_slots[idx]._handle == handle) return true; @@ -320,7 +322,7 @@ bool QSoundManager::isActive(int handle) const { return false; } -bool QSoundManager::isActive(const CWaveFile *waveFile) const { +bool QSoundManager::isActive(const CWaveFile *waveFile) { return _sounds.contains(waveFile); } diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h index a3074a8e57..ff556346de 100644 --- a/engines/titanic/sound/sound_manager.h +++ b/engines/titanic/sound/sound_manager.h @@ -123,12 +123,12 @@ public: /** * Returns true if the given sound is currently active */ - virtual bool isActive(int handle) const = 0; + virtual bool isActive(int handle) = 0; /** * Returns true if the given sound is currently active */ - virtual bool isActive(const CWaveFile *waveFile) const { return false; } + virtual bool isActive(const CWaveFile *waveFile) { return false; } /** * Handles regularly updating the mixer @@ -395,12 +395,12 @@ public: /** * Returns true if the given sound is currently active */ - virtual bool isActive(int handle) const; + virtual bool isActive(int handle); /** * Returns true if the given sound is currently active */ - virtual bool isActive(const CWaveFile *waveFile) const; + virtual bool isActive(const CWaveFile *waveFile); /** * Handles regularly updating the mixer diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp index ade94aad50..f2366d1dd5 100644 --- a/engines/titanic/sound/wave_file.cpp +++ b/engines/titanic/sound/wave_file.cpp @@ -51,9 +51,9 @@ uint CWaveFile::getDurationTicks() const { // a desired size. Since I have no idea how the system API // method works, for now I'm using a simple ratio of a // sample output to input value - uint size = _size - 0x46; - double newSize = (double)size * (1475712.0 / 199836.0); - return newSize * 1000.0 / _stream->getRate(); + uint dataSize = _size - 0x46; + double newSize = (double)dataSize * (1475712.0 / 199836.0); + return (uint)(newSize * 1000.0 / _stream->getRate()); } bool CWaveFile::loadSound(const CString &name) { @@ -106,4 +106,8 @@ uint CWaveFile::getFrequency() const { return _stream->getRate(); } +void CWaveFile::reset() { + _stream->rewind(); +} + } // End of namespace Titanic z diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h index 19d367936f..e4bb71a0b6 100644 --- a/engines/titanic/sound/wave_file.h +++ b/engines/titanic/sound/wave_file.h @@ -81,6 +81,11 @@ public: * Return the frequency of the loaded wave file */ uint getFrequency() const; + + /** + * Resets the music stream + */ + void reset(); }; } // End of namespace Titanic |