aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/sound
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/sound')
-rw-r--r--engines/titanic/sound/qmixer.cpp59
-rw-r--r--engines/titanic/sound/qmixer.h14
-rw-r--r--engines/titanic/sound/sound.cpp3
-rw-r--r--engines/titanic/sound/sound.h2
-rw-r--r--engines/titanic/sound/sound_manager.cpp6
-rw-r--r--engines/titanic/sound/sound_manager.h8
-rw-r--r--engines/titanic/sound/wave_file.cpp10
-rw-r--r--engines/titanic/sound/wave_file.h5
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