From 1e3f4f6887d2987088b6c720686cdc32c479215a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 7 Nov 2016 19:33:00 -0500 Subject: TITANIC: Simulate sound distances by reducing volume --- engines/titanic/sound/qmixer.cpp | 45 +++++++++++++++++++++++++++++++++++----- engines/titanic/sound/qmixer.h | 14 +++++++++++-- 2 files changed, 52 insertions(+), 7 deletions(-) (limited to 'engines/titanic/sound') diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp index f05f8c3ab9..ecc0bbcba4 100644 --- a/engines/titanic/sound/qmixer.cpp +++ b/engines/titanic/sound/qmixer.cpp @@ -88,11 +88,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) { @@ -168,7 +185,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()); } } @@ -182,7 +200,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) @@ -200,13 +218,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); -- cgit v1.2.3