TITANIC: Implement timed changes in volume like the original does

This commit is contained in:
Paul Gilbert
2016-09-01 20:53:01 -04:00
parent 33737ea2dc
commit d9d10d9801
7 changed files with 67 additions and 18 deletions
+4 -4
View File
@@ -468,16 +468,16 @@ void CGameObject::playGlobalSound(const CString &resName, int mode, bool initial
switch (handleIndex) {
case 0:
prox._channel = 6;
prox._channelMode = 6;
break;
case 1:
prox._channel = 7;
prox._channelMode = 7;
break;
case 2:
prox._channel = 8;
prox._channelMode = 8;
break;
case 3:
prox._channel = 9;
prox._channelMode = 9;
break;
default:
break;
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Titanic {
CProximity::CProximity() : _field4(0), _channelVolume(100), _fieldC(0),
_priorSoundHandle(-1), _field14(0), _frequencyMultiplier(0.0), _field1C(1.875),
_repeated(false), _channel(10), _positioningMode(POSMODE_NONE), _azimuth(0.0),
_repeated(false), _channelMode(10), _positioningMode(POSMODE_NONE), _azimuth(0.0),
_range(0.5), _elevation(0), _posX(0.0), _posY(0.0), _posZ(0.0),
_hasVelocity(false), _velocityX(0), _velocityY(0), _velocityZ(0),
_field54(0), _field58(0), _field5C(0), _freeSoundFlag(false), _endTalkerFn(nullptr),
+1 -1
View File
@@ -44,7 +44,7 @@ public:
double _frequencyMultiplier;
double _field1C;
bool _repeated;
int _channel;
int _channelMode;
PositioningMode _positioningMode;
double _azimuth;
double _range;
+37 -4
View File
@@ -20,6 +20,7 @@
*
*/
#include "common/system.h"
#include "titanic/sound/qmixer.h"
namespace Titanic {
@@ -63,12 +64,22 @@ void QMixer::qsWaveMixFlushChannel(int iChannel, uint flags) {
}
void QMixer::qsWaveMixSetPanRate(int iChannel, uint flags, uint rate) {
// Not currently implemented in ScummVM
ChannelEntry &channel = _channels[iChannel];
channel._panRate = rate;
channel._volumeChangeEnd = channel._volumeChangeEnd = 0;
}
void QMixer::qsWaveMixSetVolume(int iChannel, uint flags, uint volume) {
ChannelEntry &channel = _channels[iChannel];
// QMixer volumes go from 0-32767, but we need to convert to 0-255 for ScummVM
assert(volume <= 32767);
byte newVolume = (volume >= 32700) ? 255 : volume * 255 / 32767;
channel._volumeStart = newVolume;
channel._volumeEnd = volume * 255 / 100; // Convert from 0-100 (percent) to 0-255
channel._volumeChangeStart = g_system->getMillis();
channel._volumeChangeEnd = channel._volumeChangeStart + channel._panRate;
}
void QMixer::qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position) {
@@ -134,6 +145,28 @@ void QMixer::qsWaveMixPump() {
for (uint iChannel = 0; iChannel < _channels.size(); ++iChannel) {
ChannelEntry &channel = _channels[iChannel];
// If there's a transition in sound volume in progress, handle it
if (channel._volumeChangeEnd) {
byte oldVolume = channel._volume;
uint currentTicks = g_system->getMillis();
if (currentTicks >= channel._volumeChangeEnd) {
// Reached end of transition period
channel._volume = channel._volumeEnd;
channel._volumeChangeStart = channel._volumeChangeEnd = 0;
} else {
// Transition in progress, so figure out new volume
channel._volume = (int)channel._volumeStart +
((int)channel._volumeEnd - (int)channel._volumeStart) *
(int)(currentTicks - channel._volumeChangeStart) / (int)channel._panRate;
}
if (channel._volume != oldVolume && !channel._sounds.empty()
&& channel._sounds.front()._started) {
_mixer->setChannelVolume(channel._sounds.front()._soundHandle, channel._volume);
}
}
// If the playing sound on the channel is finished, then call
// the callback registered for it, and remove it from the list
if (!channel._sounds.empty()) {
@@ -144,7 +177,7 @@ void QMixer::qsWaveMixPump() {
sound._waveFile->_stream->rewind();
_mixer->playStream(sound._waveFile->_soundType,
&sound._soundHandle, sound._waveFile->_stream,
-1, 0xff, 0, DisposeAfterUse::NO);
-1, channel._volume, 0, DisposeAfterUse::NO);
} else {
// Sound is finished
if (sound._callback)
@@ -164,7 +197,7 @@ void QMixer::qsWaveMixPump() {
if (!sound._started) {
_mixer->playStream(sound._waveFile->_soundType,
&sound._soundHandle, sound._waveFile->_stream,
-1, 0xff, 0, DisposeAfterUse::NO);
-1, channel._volume, 0, DisposeAfterUse::NO);
sound._started = true;
}
}
+13
View File
@@ -186,7 +186,20 @@ class QMixer {
_started(false), _waveFile(waveFile), _callback(callback), _loops(loops), _userData(userData) {}
};
struct ChannelEntry {
// Currently playing and any following queued sounds for the channel
Common::List<SoundEntry> _sounds;
// Current channel volume
byte _volume;
// Current time in milliseconds for paning (volume) changes
uint _panRate;
// Fields used to transition between volume levels
uint _volumeChangeStart;
uint _volumeChangeEnd;
byte _volumeStart;
byte _volumeEnd;
ChannelEntry() : _volume(0), _panRate(0), _volumeChangeStart(0),
_volumeChangeEnd(0), _volumeStart(0), _volumeEnd(0) {}
};
private:
Audio::Mixer *_mixer;
+4 -1
View File
@@ -171,7 +171,7 @@ int QSoundManager::playSound(CWaveFile &waveFile, CProximity &prox) {
}
}
if (channel >= 0 || (channel = resetChannel(prox._channel)) != -1) {
if (channel >= 0 || (channel = resetChannel(prox._channelMode)) != -1) {
return playWave(&waveFile, channel, flags, prox);
}
@@ -377,6 +377,9 @@ int QSoundManager::playWave(CWaveFile *waveFile, int iChannel, uint flags, CProx
if (slotIndex == -1)
return -1;
// Set the volume
setChannelVolume(iChannel, prox._channelVolume, prox._channelMode);
switch (prox._positioningMode) {
case POSMODE_POLAR:
qsWaveMixSetPolarPosition(iChannel, 8, QSPOLAR(prox._azimuth, prox._range, prox._elevation));
@@ -490,13 +490,13 @@ void CTrueTalkManager::playSpeech(TTtalker *talker, TTroomScript *roomScript, CV
// Setup proximities
CProximity p1, p2, p3;
if (isParrot) {
p1._channel = 3;
p2._channel = 5;
p3._channel = 4;
p1._channelMode = 3;
p2._channelMode = 5;
p3._channelMode = 4;
} else {
p1._channel = 0;
p2._channel = 1;
p3._channel = 2;
p1._channelMode = 0;
p2._channelMode = 1;
p3._channelMode = 2;
}
if (milli > 0) {
@@ -513,7 +513,7 @@ void CTrueTalkManager::playSpeech(TTtalker *talker, TTroomScript *roomScript, CV
p2._elevation = 0;
}
_gameManager->_sound.stopChannel(p1._channel);
_gameManager->_sound.stopChannel(p1._channelMode);
if (view) {
p1._positioningMode = POSMODE_VECTOR;
view->getPosition(p1._posX, p1._posY, p1._posZ);