ZeroK-RTS / Zero-K

Open source RTS game running on the Spring/Recoil engine
https://zero-k.info
GNU General Public License v2.0
672 stars 204 forks source link

findings on lobby music seemingly not respecting volume settings on new track play #3693

Open GoogleFrog opened 5 years ago

GoogleFrog commented 5 years ago
https://ncry.pt/p/HWOn#0GkM3YbLL8LoT8ev6c06NG5EqFnehMPXSK4dG6r3ygg findings on lobby music seemingly not respecting volume settings on new track play I inadvertently posted on #zk instead Therefore pastebin, plus notes on tracking things down
esainane commented 5 years ago

As the paste is going to expire in a few days, I'll copy my findings here, too:

[14:29] CatLady: esainane, for the love of goddess, if you could fix the ZK lobby under linux turning music to max volume after each track change, you would be eternally blessed

...

[09:22] esainane: So following up on the complaint from 19 hours ago, it looks like spring has distinct concepts for channel volume and sound source volume [09:24] esainane: https://github.com/spring/spring/blob/develop/rts/System/Sound/OpenAL/SoundSource.cpp#L355 here we see both values being used when the volume is adjusted on a track that is already playing [09:26] esainane: Looking at the behaviour in https://github.com/ZeroK-RTS/Chobby/blob/master/LuaMenu/widgets/snd_music_lite.lua#L75 the simplest way to reproduce involves disabling the current track by setting the volume to zero, then setting the volume to 0.02 which should be functionally silent, and observing it can be heard, then setting volume to 0.04, which should be increasing the volume over the previous setting, then observing that the track can't be heard anymore [09:27] esainane: The simplest fix would be to unconditionally call Spring.SetSoundStreamVolume in the lobby music widget, so we always use both volume values [09:28] esainane: But I'm not sure if this should also be considered an issue in the engine, or in springrts lua documentation, as there's no hint at this being the functionality [09:28] esainane: aaand I spoke in wrong channel

LuaMenu/widgets/snd_music_lite.lua

StartTrack()
  Spring.Echo("Starting Track", trackName, volume)

We know that this much is working properly, see [f=-000001] Starting Track, sounds/lobbyMusic/Interstellar.ogg, 0.5

invokes Spring.PlaySoundStream(trackName, volume)

rts/Lua/LuaUnsyncedCtrl.cpp

LuaUnsyncedCtrl::PlaySoundStream(lua_State* L)
        // file, volume, enqueue
        Channels::BGMusic->StreamPlay(luaL_checksstring(L, 1), luaL_optnumber(L, 2, 1.0f), luaL_optboolean(L, 3, false));

rts/System/Sound/OpenAL/AudioChannel.cpp

void AudioChannel::StreamPlay(const std::string& filepath, float volume, bool enqueue)
        curStreamSrc->PlayStream(this, filepath, volume);

rts/System/Sound/OpenAL/SoundSource.cpp

void CSoundSource::PlayStream(IAudioChannel* channel, const std::string& file, float volume)
        curVolume = volume;

Separately, changing the volume for a track in progress:

LuaMenu/widgets/snd_music_lite.lua

local function SetTrackVolume(volume)
                Spring.SetSoundStreamVolume(volume)

or

        StartTrack(GetRandomTrack(), volume)

rts/Lua/LuaUnsyncedCtrl.cpp

int LuaUnsyncedCtrl::SetSoundStreamVolume(lua_State* L)
        Channels::BGMusic->SetVolume(luaL_checkfloat(L, 1));

rts/System/Sound/OpenAL/AudioChannel.cpp

void AudioChannel::SetVolume(float newVolume)
        volume = std::max(newVolume, 0.0f);
        for (auto it = curSources.begin(); it != curSources.end(); ++it) {
                (*it)->UpdateVolume();
        }

We see volume taking into account both the channel volume and the sound source volume when UpdateVolume is called, and only when UpdateVolume is called. curChannel is not referenced outside of assignment in SoundSource.cpp otherwise. The only time UpdateVolume is called is from rts/System/Sound/OpenAL/AudioChannel.cpp:AudioChannel::SetVolume.

AudioChannel::SetVolume is called in many places in rts/System/Sound/OpenAL/Sound.cpp, but none relevant to the background music channel outside of initial configuration (Channels::BGMusic->SetVolume(std::atoi(value.c_str()) * 0.01f);) and via rts/Lua/LuaUnsyncedCtrl.cpp. It's not going to get called every time a new track is played.

rts/System/Sound/OpenAL/SoundSource.cpp

void CSoundSource::UpdateVolume()
                alSourcef(id, AL_GAIN, curVolume * curChannel->volume);
esainane commented 4 years ago

This is still a problem