mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 03:10:22 +00:00
DIRECTOR: Make sound fade non-blocking
This commit is contained in:
parent
344c1deb32
commit
0044225060
@ -2112,7 +2112,6 @@ void LB::b_sound(int nargs) {
|
||||
TYPECHECK(firstArg, INT);
|
||||
g_director->getSoundManager()->stopSound(firstArg.u.i);
|
||||
} else if (verb.u.s->equalsIgnoreCase("fadeIn")) {
|
||||
// TODO: Check for case when sound channel changes while sound is being played.
|
||||
if (nargs > 2) {
|
||||
TYPECHECK(secondArg, INT);
|
||||
ticks = secondArg.u.i;
|
||||
@ -2121,10 +2120,10 @@ void LB::b_sound(int nargs) {
|
||||
}
|
||||
|
||||
TYPECHECK(firstArg, INT);
|
||||
g_director->getSoundManager()->playFade(firstArg.u.i, true, ticks);
|
||||
g_director->getSoundManager()->registerFade(firstArg.u.i, true, ticks);
|
||||
g_director->getCurrentMovie()->getScore()->_activeFade = firstArg.u.i;
|
||||
return;
|
||||
} else if (verb.u.s->equalsIgnoreCase("fadeOut")) {
|
||||
// TODO: Check for case when sound channel changes while sound is being played.
|
||||
if (nargs > 2) {
|
||||
TYPECHECK(secondArg, INT);
|
||||
ticks = secondArg.u.i;
|
||||
@ -2133,7 +2132,8 @@ void LB::b_sound(int nargs) {
|
||||
}
|
||||
|
||||
TYPECHECK(firstArg, INT);
|
||||
g_director->getSoundManager()->playFade(firstArg.u.i, false, ticks);
|
||||
g_director->getSoundManager()->registerFade(firstArg.u.i, false, ticks);
|
||||
g_director->getCurrentMovie()->getScore()->_activeFade = firstArg.u.i;
|
||||
return;
|
||||
} else if (verb.u.s->equalsIgnoreCase("playFile")) {
|
||||
ARGNUMCHECK(3)
|
||||
|
@ -279,6 +279,11 @@ void Score::update() {
|
||||
_waitForChannel = 0;
|
||||
}
|
||||
|
||||
if (_activeFade) {
|
||||
if (!_soundManager->fadeChannel(_activeFade))
|
||||
_activeFade = 0;
|
||||
}
|
||||
|
||||
if (g_system->getMillis() < _nextFrameTime && !debugChannelSet(-1, kDebugFast)) {
|
||||
return;
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
PlayState _playState;
|
||||
uint32 _nextFrameTime;
|
||||
int _waitForChannel;
|
||||
int _activeFade;
|
||||
Cursor *_currentCursor;
|
||||
|
||||
int _numChannelsDisplayed;
|
||||
|
@ -77,6 +77,7 @@ void DirectorSound::playFile(Common::String filename, uint8 soundChannel) {
|
||||
AudioFileDecoder af(filename);
|
||||
Audio::RewindableAudioStream *sound = af.getAudioStream(DisposeAfterUse::YES);
|
||||
|
||||
cancelFade(soundChannel);
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, sound, -1, _channels[soundChannel - 1].volume);
|
||||
}
|
||||
|
||||
@ -94,6 +95,7 @@ void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
cancelFade(soundChannel);
|
||||
_mixer->stopHandle(_channels[soundChannel - 1].handle);
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, &stream, -1, _channels[soundChannel - 1].volume);
|
||||
}
|
||||
@ -133,42 +135,60 @@ void DirectorSound::playCastMember(int castId, uint8 soundChannel, bool allowRep
|
||||
}
|
||||
}
|
||||
|
||||
void DirectorSound::playFade(uint8 soundChannel, bool fadeIn, int ticks) {
|
||||
void DirectorSound::registerFade(uint8 soundChannel, bool fadeIn, int ticks) {
|
||||
if (soundChannel == 0 || soundChannel > _channels.size()) {
|
||||
warning("Invalid sound channel %d", soundChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
Audio::SoundHandle handle = _channels[soundChannel - 1].handle;
|
||||
cancelFade(soundChannel);
|
||||
|
||||
if (!isChannelActive(soundChannel))
|
||||
return;
|
||||
int startVol = fadeIn ? 0 : _channels[soundChannel - 1].volume;
|
||||
int targetVol = fadeIn ? _channels[soundChannel - 1].volume : 0;
|
||||
|
||||
float startVolume = fadeIn ? 0 : _channels[soundChannel - 1].volume;
|
||||
float targetVolume = fadeIn ? _channels[soundChannel - 1].volume : 0;
|
||||
int lastVolume = 0;
|
||||
_channels[soundChannel - 1].fade = new FadeParams(startVol, targetVol, ticks, _vm->getMacTicks(), fadeIn);
|
||||
_mixer->setChannelVolume(_channels[soundChannel - 1].handle, startVol);
|
||||
}
|
||||
|
||||
_mixer->setChannelVolume(handle, startVolume);
|
||||
|
||||
int startTicks = _vm->getMacTicks();
|
||||
int lapsedTicks = 0, lastTicks = 0;
|
||||
|
||||
while (lapsedTicks < ticks) {
|
||||
lapsedTicks = _vm->getMacTicks() - startTicks;
|
||||
if (lapsedTicks == lastTicks)
|
||||
continue;
|
||||
|
||||
lastTicks = lapsedTicks;
|
||||
if (fadeIn) {
|
||||
lastVolume = MIN(lapsedTicks * (targetVolume / ticks), (float)Audio::Mixer::kMaxChannelVolume);
|
||||
} else {
|
||||
lastVolume = MAX((ticks - lapsedTicks) * (startVolume / ticks), (float)0);
|
||||
}
|
||||
|
||||
_mixer->setChannelVolume(handle, lastVolume);
|
||||
bool DirectorSound::fadeChannel(uint8 soundChannel) {
|
||||
if (soundChannel == 0 || soundChannel > _channels.size()) {
|
||||
warning("Invalid sound channel %d", soundChannel);
|
||||
return false;
|
||||
} else if (!isChannelActive(soundChannel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_mixer->setChannelVolume(handle, targetVolume);
|
||||
FadeParams *fade = _channels[soundChannel - 1].fade;
|
||||
if (!fade)
|
||||
return false;
|
||||
|
||||
fade->lapsedTicks = _vm->getMacTicks() - fade->startTicks;
|
||||
if (fade->lapsedTicks > fade->totalTicks) {
|
||||
cancelFade(soundChannel);
|
||||
return false;
|
||||
}
|
||||
|
||||
int fadeVol;
|
||||
if (fade->fadeIn) {
|
||||
fadeVol = MIN(fade->lapsedTicks * ((float)fade->targetVol / fade->totalTicks), (float)Audio::Mixer::kMaxChannelVolume);
|
||||
} else {
|
||||
fadeVol = MAX((fade->totalTicks - fade->lapsedTicks) * ((float)fade->startVol / fade->totalTicks), (float)0);
|
||||
}
|
||||
|
||||
_mixer->setChannelVolume(_channels[soundChannel - 1].handle, fadeVol);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DirectorSound::cancelFade(uint8 soundChannel) {
|
||||
// NOTE: It is assumed that soundChannel has already been validated, which is
|
||||
// why this method is private.
|
||||
|
||||
if (_channels[soundChannel - 1].fade) {
|
||||
_mixer->setChannelVolume(_channels[soundChannel - 1].handle, _channels[soundChannel - 1].fade->targetVol);
|
||||
|
||||
delete _channels[soundChannel - 1].fade;
|
||||
_channels[soundChannel - 1].fade = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectorSound::isChannelActive(uint8 soundChannel) {
|
||||
@ -195,6 +215,7 @@ void DirectorSound::stopSound(uint8 soundChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
cancelFade(soundChannel);
|
||||
_mixer->stopHandle(_channels[soundChannel - 1].handle);
|
||||
_channels[soundChannel - 1].lastPlayingCast = 0;
|
||||
return;
|
||||
@ -202,9 +223,12 @@ void DirectorSound::stopSound(uint8 soundChannel) {
|
||||
|
||||
void DirectorSound::stopSound() {
|
||||
for (uint i = 0; i < _channels.size(); i++) {
|
||||
cancelFade(i);
|
||||
|
||||
_mixer->stopHandle(_channels[i].handle);
|
||||
_channels[i].lastPlayingCast = 0;
|
||||
}
|
||||
|
||||
_mixer->stopHandle(*_scriptSound);
|
||||
_mixer->stopHandle(*_pcSpeakerHandle);
|
||||
}
|
||||
|
@ -34,12 +34,25 @@ namespace Audio {
|
||||
|
||||
namespace Director {
|
||||
|
||||
struct FadeParams {
|
||||
int startVol;
|
||||
int targetVol;
|
||||
int totalTicks;
|
||||
int startTicks;
|
||||
int lapsedTicks;
|
||||
bool fadeIn;
|
||||
|
||||
FadeParams(int sv, int tv, int tt, int st, bool f) :
|
||||
startVol(sv), targetVol(tv), totalTicks(tt), startTicks(st), lapsedTicks(0), fadeIn(f) {}
|
||||
};
|
||||
|
||||
struct SoundChannel {
|
||||
Audio::SoundHandle handle;
|
||||
int lastPlayingCast;
|
||||
byte volume;
|
||||
FadeParams *fade;
|
||||
|
||||
SoundChannel(): handle(), lastPlayingCast(0), volume(255) {}
|
||||
SoundChannel(): handle(), lastPlayingCast(0), volume(255), fade(nullptr) {}
|
||||
};
|
||||
|
||||
class DirectorSound {
|
||||
@ -61,13 +74,18 @@ public:
|
||||
void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
|
||||
void playStream(Audio::AudioStream &stream, uint8 soundChannel);
|
||||
void playCastMember(int castId, uint8 soundChannel, bool allowRepeat = true);
|
||||
void playFade(uint8 soundChannel, bool fadeIn, int ticks);
|
||||
void systemBeep();
|
||||
|
||||
void registerFade(uint8 soundChannel, bool fadeIn, int ticks);
|
||||
bool fadeChannel(uint8 soundChannel);
|
||||
|
||||
bool isChannelActive(uint8 soundChannel);
|
||||
int lastPlayingCast(uint8 soundChannel);
|
||||
void stopSound(uint8 soundChannel);
|
||||
void stopSound();
|
||||
|
||||
private:
|
||||
void cancelFade(uint8 soundChannel);
|
||||
};
|
||||
|
||||
class AudioDecoder {
|
||||
|
Loading…
Reference in New Issue
Block a user