mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
TITANIC: Implement timed changes in volume like the original does
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
double _frequencyMultiplier;
|
||||
double _field1C;
|
||||
bool _repeated;
|
||||
int _channel;
|
||||
int _channelMode;
|
||||
PositioningMode _positioningMode;
|
||||
double _azimuth;
|
||||
double _range;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user