Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Clean up sound_fade (#10119)
Add proper documentation and correct gain reduction calculations.

Co-authored-by: hecktest <>
  • Loading branch information
hecktest committed Aug 19, 2020
1 parent 649211b commit 5bda361
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
7 changes: 5 additions & 2 deletions doc/lua_api.txt
Expand Up @@ -5238,9 +5238,12 @@ Sounds
* `minetest.sound_fade(handle, step, gain)`
* `handle` is a handle returned by `minetest.sound_play`
* `step` determines how fast a sound will fade.
Negative step will lower the sound volume, positive step will increase
the sound volume.
The gain will change by this much per second,
until it reaches the target gain.
Note: Older versions used a signed step. This is deprecated, but old
code will still work. (the client uses abs(step) to correct it)
* `gain` the target gain for the fade.
Fading to zero will delete the sound.

Timing
------
Expand Down
55 changes: 30 additions & 25 deletions src/client/sound_openal.cpp
Expand Up @@ -337,14 +337,12 @@ class OpenALSoundManager: public ISoundManager
};

std::unordered_map<int, FadeState> m_sounds_fading;
float m_fade_delay;
public:
OpenALSoundManager(SoundManagerSingleton *smg, OnDemandSoundFetcher *fetcher):
m_fetcher(fetcher),
m_device(smg->m_device.get()),
m_context(smg->m_context.get()),
m_next_id(1),
m_fade_delay(0)
m_next_id(1)
{
infostream << "Audio: Initialized: OpenAL " << std::endl;
}
Expand Down Expand Up @@ -616,38 +614,45 @@ class OpenALSoundManager: public ISoundManager

void fadeSound(int soundid, float step, float gain)
{
m_sounds_fading[soundid] = FadeState(step, getSoundGain(soundid), gain);
// Ignore the command if step isn't valid.
if (step == 0)
return;
float current_gain = getSoundGain(soundid);
step = gain - current_gain > 0 ? abs(step) : -abs(step);
if (m_sounds_fading.find(soundid) != m_sounds_fading.end()) {
auto current_fade = m_sounds_fading[soundid];
// Do not replace the fade if it's equivalent.
if (current_fade.target_gain == gain && current_fade.step == step)
return;
m_sounds_fading.erase(soundid);
}
gain = rangelim(gain, 0, 1);
m_sounds_fading[soundid] = FadeState(step, current_gain, gain);
}

void doFades(float dtime)
{
m_fade_delay += dtime;

if (m_fade_delay < 0.1f)
return;
for (auto i = m_sounds_fading.begin(); i != m_sounds_fading.end();) {
FadeState& fade = i->second;
assert(fade.step != 0);
fade.current_gain += (fade.step * dtime);

float chkGain = 0;
for (auto i = m_sounds_fading.begin();
i != m_sounds_fading.end();) {
if (i->second.step < 0.f)
chkGain = -(i->second.current_gain);
if (fade.step < 0.f)
fade.current_gain = std::max(fade.current_gain, fade.target_gain);
else
chkGain = i->second.current_gain;
fade.current_gain = std::min(fade.current_gain, fade.target_gain);

if (chkGain < i->second.target_gain) {
i->second.current_gain += (i->second.step * m_fade_delay);
i->second.current_gain = rangelim(i->second.current_gain, 0, 1);

updateSoundGain(i->first, i->second.current_gain);
++i;
} else {
if (i->second.target_gain <= 0.f)
stopSound(i->first);
if (fade.current_gain <= 0.f)
stopSound(i->first);
else
updateSoundGain(i->first, fade.current_gain);

// The increment must happen during the erase call, or else it'll segfault.
if (fade.current_gain == fade.target_gain)
m_sounds_fading.erase(i++);
}
else
i++;
}
m_fade_delay = 0;
}

bool soundExists(int sound)
Expand Down

0 comments on commit 5bda361

Please sign in to comment.