From 133b415b846d96821dde42fd489e7f9343dfca3a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Dec 2023 13:43:41 +0100 Subject: [PATCH] music volume. * this now applies the factor to the source data instead of setting a gain factor in OpenAL to allow better control * $musicvolume will now also accept values in dB, by postfixing the parameter with 'dB'. * removed some useless cruft from the automatic replay gain handling. --- src/common/audio/music/music.cpp | 51 ++++++++++++++++---------------- src/common/audio/music/s_music.h | 3 +- src/sound/s_advsound.cpp | 12 +++++++- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 43e05cb5c6..8749f4ba33 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -57,6 +57,7 @@ #include "c_cvars.h" #include "md5.h" + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern int nomusic; @@ -94,11 +95,6 @@ EXTERN_CVAR(Float, fluid_gain) CVAR(Bool, mus_calcgain, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. CVAR(Bool, mus_usereplaygain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. -CUSTOM_CVAR(Float, mus_gainoffset, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // for customizing the base volume -{ - if (self > 10.f) self = 10.f; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); -} // CODE -------------------------------------------------------------------- @@ -167,12 +163,12 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) if (mus_playing.isfloat) { written = ZMusic_FillStream(mus_playing.handle, buff, len); - if (mus_playing.replayGainFactor != 1.f) + if (mus_playing.musicVolume != 1.f) { float* fbuf = (float*)buff; for (int i = 0; i < len / 4; i++) { - fbuf[i] *= mus_playing.replayGainFactor; + fbuf[i] *= mus_playing.musicVolume; } } } @@ -184,7 +180,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) float* fbuf = (float*)buff; for (int i = 0; i < len / 4; i++) { - fbuf[i] = convert[i] * mus_playing.replayGainFactor * (1.f/32768.f); + fbuf[i] = convert[i] * mus_playing.musicVolume * (1.f/32768.f); } } @@ -508,21 +504,19 @@ CCMD(setreplaygain) if (argv.argc() < 2) { Printf("Usage: setreplaygain {dB}\n"); - Printf("Current replay gain is %f dB\n", mus_playing.replayGain); + Printf("Current replay gain is %f dB\n", AmplitudeTodB(mus_playing.musicVolume)); return; } float dB = (float)strtod(argv[1], nullptr); if (dB > 10) dB = 10; // don't blast the speakers. Values above 2 or 3 are very rare. gainMap.Insert(mus_playing.hash, dB); SaveGains(); - mus_playing.replayGain = dB; - mus_playing.replayGainFactor = (float)dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = (float)dBToAmplitude(dB); } static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const char *playparam) { - mus_playing.replayGain = 0.f; - mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset); + mus_playing.musicVolume = 1; fluid_gain->Callback(); mod_dumb_mastervolume->Callback(); if (!mus_usereplaygain) return; @@ -539,8 +533,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const auto entry = gainMap.CheckKey(hash); if (entry) { - mus_playing.replayGain = *entry; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = dBToAmplitude(*entry); return; } if (!mus_calcgain) return; @@ -624,19 +617,18 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const } ZMusic_Close(handle); - GainAnalyzer analyzer; - int result = analyzer.InitGainAnalysis(fmt.mSampleRate); + auto analyzer = std::make_unique(); + int result = analyzer->InitGainAnalysis(fmt.mSampleRate); if (result == GAIN_ANALYSIS_OK) { - result = analyzer.AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2); + result = analyzer->AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2); if (result == GAIN_ANALYSIS_OK) { - auto gain = analyzer.GetTitleGain(); - Printf("Calculated replay gain for %s at %f dB\n", hash.GetChars(), gain); + auto gain = analyzer->GetTitleGain(); + Printf("Calculated replay gain for %s (%s) at %f dB\n", musicname, hash.GetChars(), gain); gainMap.Insert(hash, gain); - mus_playing.replayGain = gain; - mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset); + mus_playing.musicVolume = dBToAmplitude(gain); SaveGains(); } } @@ -726,8 +718,16 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) } else { + auto volp = MusicVolumes.CheckKey(musicname); + if (volp) + { + mus_playing.musicVolume = *volp; - CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); + } + else + { + CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); + } auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper. mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); if (mus_playing.handle == nullptr) @@ -743,13 +743,12 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) if (mus_playing.handle != 0) { // play it - auto volp = MusicVolumes.CheckKey(musicname); - float vol = volp ? *volp : 1.f; - if (!S_StartMusicPlaying(mus_playing.handle, looping, vol, order)) + if (!S_StartMusicPlaying(mus_playing.handle, looping, 1.f, order)) { Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError()); return false; } + S_CreateStream(); mus_playing.baseorder = order; return true; diff --git a/src/common/audio/music/s_music.h b/src/common/audio/music/s_music.h index 6ae4017c9e..e697613cde 100644 --- a/src/common/audio/music/s_music.h +++ b/src/common/audio/music/s_music.h @@ -79,8 +79,7 @@ struct MusPlayingInfo FString name; ZMusic_MusicStream handle; int baseorder; - float replayGain; - float replayGainFactor; + float musicVolume; bool loop; bool isfloat; FString LastSong; // last music that was played diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index c354de1aa0..85fdf5344c 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -49,6 +49,7 @@ #include "vm.h" #include "i_system.h" #include "s_music.h" +#include "i_music.h" using namespace FileSys; @@ -134,6 +135,7 @@ enum SICommands SI_Registered, SI_ArchivePath, SI_MusicVolume, + SI_Replaygain, SI_MidiDevice, SI_IfDoom, SI_IfHeretic, @@ -222,6 +224,7 @@ static const char *SICommandStrings[] = "$registered", "$archivepath", "$musicvolume", + "$replaygain", "$mididevice", "$ifdoom", "$ifheretic", @@ -1032,7 +1035,14 @@ static void S_AddSNDINFO (int lump) case SI_MusicVolume: { sc.MustGetString(); FName musname (sc.String); - sc.MustGetFloat(); + if (!sc.CheckFloat()) + { + sc.MustGetString(); + char* p; + double f = strtod(sc.String, &p); + if (!stricmp(p, "db")) sc.Float = dBToAmplitude((float)sc.Float); + else sc.ScriptError("Bad value for music volume: %s", sc.String); + } MusicVolumes[musname] = (float)sc.Float; } break;