mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-02 08:55:45 +00:00
SCI32: Use better audio fading algorithm
Using the one from SCI2.1mid makes fades very slow because SDL has a larger audio buffer than SSCI DOS. This new algorithm is based on wall time so will always fade at the correct speed, although the larger buffers will have a coarser granularity so the fades may not be as smooth as in the original engine. If anyone cares, the fade volume could be mixed into individual samples in `readBuffer` instead of applying just once per complete buffer. SSCI did not do this, however, so this implementation should be pretty accurate.
This commit is contained in:
parent
e8552cf96c
commit
b7dcf5f6c1
@ -305,7 +305,7 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) {
|
|||||||
|
|
||||||
// Channel finished fading and had the
|
// Channel finished fading and had the
|
||||||
// stopChannelOnFade flag set, so no longer exists
|
// stopChannelOnFade flag set, so no longer exists
|
||||||
if (channel.fadeStepsRemaining && processFade(channelIndex)) {
|
if (channel.fadeStartTick && processFade(channelIndex)) {
|
||||||
--channelIndex;
|
--channelIndex;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -602,8 +602,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
|
|||||||
channel.loop = loop;
|
channel.loop = loop;
|
||||||
channel.robot = false;
|
channel.robot = false;
|
||||||
channel.vmd = false;
|
channel.vmd = false;
|
||||||
channel.lastFadeTick = 0;
|
channel.fadeStartTick = 0;
|
||||||
channel.fadeStepsRemaining = 0;
|
|
||||||
channel.soundNode = soundNode;
|
channel.soundNode = soundNode;
|
||||||
channel.volume = volume < 0 || volume > kMaxVolume ? (int)kMaxVolume : volume;
|
channel.volume = volume < 0 || volume > kMaxVolume ? (int)kMaxVolume : volume;
|
||||||
// TODO: SCI3 introduces stereo audio
|
// TODO: SCI3 introduces stereo audio
|
||||||
@ -927,12 +926,12 @@ bool Audio32::fadeChannel(const int16 channelIndex, const int16 targetVolume, co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (steps) {
|
if (steps && speed) {
|
||||||
channel.fadeVolume = targetVolume;
|
channel.fadeStartTick = g_sci->getTickCount();
|
||||||
channel.fadeSpeed = speed;
|
channel.fadeStartVolume = channel.volume;
|
||||||
channel.fadeStepsRemaining = steps;
|
channel.fadeTargetVolume = targetVolume;
|
||||||
|
channel.fadeDuration = speed * steps;
|
||||||
channel.stopChannelOnFade = stopAfterFade;
|
channel.stopChannelOnFade = stopAfterFade;
|
||||||
channel.lastFadeTick = g_sci->getTickCount();
|
|
||||||
} else {
|
} else {
|
||||||
setVolume(channelIndex, targetVolume);
|
setVolume(channelIndex, targetVolume);
|
||||||
}
|
}
|
||||||
@ -944,28 +943,28 @@ bool Audio32::processFade(const int16 channelIndex) {
|
|||||||
Common::StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
AudioChannel &channel = getChannel(channelIndex);
|
AudioChannel &channel = getChannel(channelIndex);
|
||||||
|
|
||||||
uint32 now = g_sci->getTickCount();
|
if (channel.fadeStartTick) {
|
||||||
|
const uint32 fadeElapsed = g_sci->getTickCount() - channel.fadeStartTick;
|
||||||
if (channel.lastFadeTick + channel.fadeSpeed <= now) {
|
if (fadeElapsed > channel.fadeDuration) {
|
||||||
--channel.fadeStepsRemaining;
|
channel.fadeStartTick = 0;
|
||||||
|
|
||||||
if (!channel.fadeStepsRemaining) {
|
|
||||||
if (channel.stopChannelOnFade) {
|
if (channel.stopChannelOnFade) {
|
||||||
stop(channelIndex);
|
stop(channelIndex);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
setVolume(channelIndex, channel.fadeVolume);
|
setVolume(channelIndex, channel.fadeTargetVolume);
|
||||||
}
|
}
|
||||||
} else {
|
return false;
|
||||||
int volume = channel.volume - (channel.volume - channel.fadeVolume) / (channel.fadeStepsRemaining + 1);
|
|
||||||
|
|
||||||
if (volume == channel.fadeVolume) {
|
|
||||||
channel.fadeStepsRemaining = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
setVolume(channelIndex, volume);
|
|
||||||
channel.lastFadeTick = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int volume;
|
||||||
|
if (channel.fadeStartVolume > channel.fadeTargetVolume) {
|
||||||
|
volume = channel.fadeStartVolume - fadeElapsed * (channel.fadeStartVolume - channel.fadeTargetVolume) / channel.fadeDuration;
|
||||||
|
} else {
|
||||||
|
volume = channel.fadeStartVolume + fadeElapsed * (channel.fadeTargetVolume - channel.fadeStartVolume) / channel.fadeDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
setVolume(channelIndex, volume);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -90,27 +90,25 @@ struct AudioChannel {
|
|||||||
bool loop;
|
bool loop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time the last fade iteration occurred.
|
* The time, in ticks, that the channel fade began.
|
||||||
|
* If 0, the channel is not being faded.
|
||||||
*/
|
*/
|
||||||
uint32 lastFadeTick;
|
uint32 fadeStartTick;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The target volume of the fade.
|
* The start volume of a fade.
|
||||||
*/
|
*/
|
||||||
int fadeVolume;
|
int fadeStartVolume;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of ticks that should elapse between
|
* The total length of the fade, in ticks.
|
||||||
* each change of volume.
|
|
||||||
*/
|
*/
|
||||||
int fadeSpeed;
|
uint32 fadeDuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of iterations the fade should take to
|
* The end volume of a fade.
|
||||||
* complete. If this value is 0, it indicates that the
|
|
||||||
* channel is not fading.
|
|
||||||
*/
|
*/
|
||||||
int fadeStepsRemaining;
|
uint32 fadeTargetVolume;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the channel should be stopped and
|
* Whether or not the channel should be stopped and
|
||||||
|
Loading…
x
Reference in New Issue
Block a user