From dc01c3911a1c830065726e93d2d64714ff615dbf Mon Sep 17 00:00:00 2001 From: Dale Whinham Date: Thu, 3 Mar 2022 16:23:17 +0000 Subject: [PATCH] Add ability to override gain per-SoundFont Closes #248. --- CHANGELOG.md | 1 + include/config.def | 2 +- include/synth/fxprofile.h | 2 ++ include/synth/soundfontsynth.h | 5 ++--- sdcard/mt32-pi.cfg | 19 ++++++------------- src/config.cpp | 2 ++ src/mt32pi.cpp | 2 +- src/synth/soundfontsynth.cpp | 23 ++++++++++++++--------- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dea3718..a0ec5c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Update to FluidSynth v2.2.5. +- FluidSynth's master volume gain is now an effects profile setting and can be overridden on a per-SoundFont basis (issue #248). Thanks to @c0d3h4x0r for the suggestion! ### Fixed diff --git a/include/config.def b/include/config.def index 8f6d6d4..f176aec 100644 --- a/include/config.def +++ b/include/config.def @@ -76,8 +76,8 @@ END_SECTION BEGIN_SECTION(fluidsynth) CFG(soundfont, int, FluidSynthSoundFont, 0 ) -CFG(gain, float, FluidSynthGain, 0.2f ) CFG(polyphony, int, FluidSynthPolyphony, 200 ) +CFG(gain, float, FluidSynthDefaultGain, 0.2f ) CFG(reverb, bool, FluidSynthDefaultReverbActive, true ) CFG(reverb_damping, float, FluidSynthDefaultReverbDamping, 0.0 ) CFG(reverb_level, float, FluidSynthDefaultReverbLevel, 0.9 ) diff --git a/include/synth/fxprofile.h b/include/synth/fxprofile.h index 39e1a48..c16424d 100644 --- a/include/synth/fxprofile.h +++ b/include/synth/fxprofile.h @@ -27,6 +27,8 @@ struct TFXProfile { + TOptional nGain; + TOptional bReverbActive; TOptional nReverbDamping; TOptional nReverbLevel; diff --git a/include/synth/soundfontsynth.h b/include/synth/soundfontsynth.h index a1393b3..a4f75c1 100644 --- a/include/synth/soundfontsynth.h +++ b/include/synth/soundfontsynth.h @@ -34,7 +34,7 @@ class CSoundFontSynth : public CSynthBase { public: - CSoundFontSynth(unsigned nSampleRate, float nGain = 0.2f, u32 nPolyphony = 256); + CSoundFontSynth(unsigned nSampleRate); virtual ~CSoundFontSynth() override; // CSynthBase @@ -66,10 +66,9 @@ class CSoundFontSynth : public CSynthBase fluid_settings_t* m_pSettings; fluid_synth_t* m_pSynth; + u8 m_nVolume; float m_nInitialGain; - float m_nCurrentGain; - u32 m_nPolyphony; u16 m_nPercussionMask; size_t m_nCurrentSoundFontIndex; diff --git a/sdcard/mt32-pi.cfg b/sdcard/mt32-pi.cfg index 85b3a13..8c757a1 100644 --- a/sdcard/mt32-pi.cfg +++ b/sdcard/mt32-pi.cfg @@ -302,17 +302,6 @@ reversed_stereo = off # Values: 0-255 (0*) soundfont = 0 -# Set the master volume gain. -# -# The default is a low value to avoid clipping when many notes are playing at -# once. -# -# The value should be a decimal value between 0.0 and 10.0. Values outside this -# range will be clamped. -# -# Values: 0.0-10.0 (0.2*) -gain = 0.2 - # Set the maximum number of voices that can be played simultaneously. # # Depending on the complexity of your SoundFont, you may need to reduce this @@ -329,8 +318,8 @@ gain = 0.2 # Values: 1-65535 (200*) polyphony = 200 -# The following settings set the default parameters for FluidSynth's reverb and -# chorus effects. +# The following settings set the default parameters for FluidSynth's master +# voluime gain, reverb and chorus effects. # # Each setting can be overridden on a per-SoundFont basis by adding extra # sections, e.g. [fluidsynth.soundfont.x], where x is the zero-based index of @@ -338,6 +327,8 @@ polyphony = 200 # # Full descriptions and valid value ranges for each setting can be found in the # FluidSynth documentation: https://www.fluidsynth.org/api/fluidsettings.xml +gain = 0.2 + reverb = on reverb_damping = 0.0 reverb_level = 0.9 @@ -356,6 +347,8 @@ chorus_speed = 0.3 [fluidsynth.soundfont.0] # The following settings are recommended for GeneralUser GS by its author. +gain = 0.2 + reverb = on reverb_damping = 0.19 reverb_level = 0.5 diff --git a/src/config.cpp b/src/config.cpp index 3f32c8a..50d989a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -144,6 +144,8 @@ bool CConfig::ParseFXProfileOption(const char* pString, const char* pValue, TFXP return false; \ } + MATCH("gain", float, nGain); + MATCH("reverb", bool, bReverbActive); MATCH("reverb_damping", float, nReverbDamping); MATCH("reverb_level", float, nReverbLevel); diff --git a/src/mt32pi.cpp b/src/mt32pi.cpp index cd34631..71a2af7 100644 --- a/src/mt32pi.cpp +++ b/src/mt32pi.cpp @@ -392,7 +392,7 @@ bool CMT32Pi::InitSoundFontSynth() { assert(m_pSoundFontSynth == nullptr); - m_pSoundFontSynth = new CSoundFontSynth(m_pConfig->AudioSampleRate, m_pConfig->FluidSynthGain, m_pConfig->FluidSynthPolyphony); + m_pSoundFontSynth = new CSoundFontSynth(m_pConfig->AudioSampleRate); if (!m_pSoundFontSynth->Initialize()) { m_pLogger->Write(MT32PiName, LogWarning, "FluidSynth init failed; no SoundFonts present?"); diff --git a/src/synth/soundfontsynth.cpp b/src/synth/soundfontsynth.cpp index 09321ea..4349f2b 100644 --- a/src/synth/soundfontsynth.cpp +++ b/src/synth/soundfontsynth.cpp @@ -129,16 +129,15 @@ extern "C" } } -CSoundFontSynth::CSoundFontSynth(unsigned nSampleRate, float nGain, u32 nPolyphony) +CSoundFontSynth::CSoundFontSynth(unsigned nSampleRate) : CSynthBase(nSampleRate), m_pSettings(nullptr), m_pSynth(nullptr), - m_nInitialGain(nGain), - m_nCurrentGain(nGain), + m_nVolume(100), + m_nInitialGain(0.2f), - m_nPolyphony(nPolyphony), m_nPercussionMask(1 << 9), m_nCurrentSoundFontIndex(0) { @@ -298,9 +297,9 @@ void CSoundFontSynth::AllSoundOff() void CSoundFontSynth::SetMasterVolume(u8 nVolume) { - m_nCurrentGain = nVolume / 100.0f * m_nInitialGain; + m_nVolume = nVolume; m_Lock.Acquire(); - fluid_synth_set_gain(m_pSynth, m_nCurrentGain); + fluid_synth_set_gain(m_pSynth, m_nVolume / 100.0f * m_nInitialGain); m_Lock.Release(); } @@ -393,8 +392,10 @@ bool CSoundFontSynth::Reinitialize(const char* pSoundFontPath, const TFXProfile* return false; } - fluid_synth_set_gain(m_pSynth, m_nCurrentGain); - fluid_synth_set_polyphony(m_pSynth, m_nPolyphony); + fluid_synth_set_polyphony(m_pSynth, pConfig->FluidSynthPolyphony); + + m_nInitialGain = pFXProfile->nGain.ValueOr(pConfig->FluidSynthDefaultGain); + fluid_synth_set_gain(m_pSynth, m_nVolume / 100.0f * m_nInitialGain); // Use values from effects profile if set, otherwise use defaults fluid_synth_reverb_on(m_pSynth, -1, pFXProfile->bReverbActive.ValueOr(pConfig->FluidSynthDefaultReverbActive)); @@ -442,9 +443,11 @@ void CSoundFontSynth::ResetMIDIMonitor() void CSoundFontSynth::DumpFXSettings() const { CLogger* const pLogger = CLogger::Get(); - double nReverbDamping, nReverbLevel, nReverbRoomSize, nReverbWidth, nChorusDepth, nChorusLevel, nChorusSpeed; + double nGain, nReverbDamping, nReverbLevel, nReverbRoomSize, nReverbWidth, nChorusDepth, nChorusLevel, nChorusSpeed; int nChorusVoices; + nGain = fluid_synth_get_gain(m_pSynth); + assert(fluid_synth_get_reverb_group_damp(m_pSynth, -1, &nReverbDamping) == FLUID_OK); assert(fluid_synth_get_reverb_group_level(m_pSynth, -1, &nReverbLevel) == FLUID_OK); assert(fluid_synth_get_reverb_group_roomsize(m_pSynth, -1, &nReverbRoomSize) == FLUID_OK); @@ -455,6 +458,8 @@ void CSoundFontSynth::DumpFXSettings() const assert(fluid_synth_get_chorus_group_nr(m_pSynth, -1, &nChorusVoices) == FLUID_OK); assert(fluid_synth_get_chorus_group_speed(m_pSynth, -1, &nChorusSpeed) == FLUID_OK); + pLogger->Write(SoundFontSynthName, LogNotice, "Gain: %.2f", nGain); + pLogger->Write(SoundFontSynthName, LogNotice, "Reverb: %.2f, %.2f, %.2f, %.2f", nReverbDamping,