Skip to content

Commit

Permalink
Reinitialize the Midi libraries when returning to the game browser.
Browse files Browse the repository at this point in the history
Now custom soundfonts are always loaded when switching the game instead of only the first time.

Fix #2916
  • Loading branch information
Ghabry committed Sep 22, 2023
1 parent 7269d32 commit 5bb2a26
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 33 deletions.
13 changes: 13 additions & 0 deletions src/audio_midi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,16 @@ std::unique_ptr<AudioDecoderBase> MidiDecoder::CreateFmMidi(bool resample) {

return mididec;
}

void MidiDecoder::Reset() {
works.fluidsynth = true;
works.wildmidi = true;

#ifdef HAVE_LIBWILDMIDI
WildMidiDecoder::ResetState();
#endif

#if defined(HAVE_FLUIDSYNTH) || defined(HAVE_FLUIDLITE)
FluidSynthDecoder::ResetState();
#endif
}
5 changes: 5 additions & 0 deletions src/audio_midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ class MidiDecoder {

static std::unique_ptr<AudioDecoderBase> CreateFmMidi(bool resample);

/**
* Resets the global state of the midi libraries.
*/
static void Reset();

protected:
int frequency = EP_MIDI_FREQ;
};
Expand Down
58 changes: 31 additions & 27 deletions src/decoder_fluidsynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ static fluid_fileapi_t fluidlite_vio = {

namespace {
std::string preferred_soundfont;

bool once = false;
bool init = false;
}

struct FluidSynthDeleter {
Expand Down Expand Up @@ -208,10 +211,7 @@ FluidSynthDecoder::~FluidSynthDecoder() {
}

bool FluidSynthDecoder::Initialize(std::string& error_message) {
static bool init = false;
static bool once = false;

// only initialize once
// only initialize once until a new game starts
if (once)
return init;
once = true;
Expand All @@ -220,47 +220,51 @@ bool FluidSynthDecoder::Initialize(std::string& error_message) {
fluid_set_default_fileapi(&fluidlite_vio);
#endif

global_settings.reset(new_fluid_settings());
if (!global_settings) {
global_settings.reset(new_fluid_settings());
if (!global_settings) {
return false;
}
fluid_settings_setstr(global_settings.get(), "player.timing-source", "sample");
fluid_settings_setint(global_settings.get(), "synth.lock-memory", 0);
return false;
}
fluid_settings_setstr(global_settings.get(), "player.timing-source", "sample");
fluid_settings_setint(global_settings.get(), "synth.lock-memory", 0);

fluid_settings_setnum(global_settings.get(), "synth.gain", 0.6);
fluid_settings_setnum(global_settings.get(), "synth.sample-rate", EP_MIDI_FREQ);
fluid_settings_setint(global_settings.get(), "synth.polyphony", 256);
fluid_settings_setnum(global_settings.get(), "synth.gain", 0.6);
fluid_settings_setnum(global_settings.get(), "synth.sample-rate", EP_MIDI_FREQ);
fluid_settings_setint(global_settings.get(), "synth.polyphony", 256);

#if defined(HAVE_FLUIDSYNTH) && FLUIDSYNTH_VERSION_MAJOR > 1
fluid_settings_setint(global_settings.get(), "synth.reverb.active", 0);
fluid_settings_setint(global_settings.get(), "synth.chorus.active", 0);
fluid_settings_setint(global_settings.get(), "synth.reverb.active", 0);
fluid_settings_setint(global_settings.get(), "synth.chorus.active", 0);
#else
fluid_settings_setstr(global_settings.get(), "synth.reverb.active", "no");
fluid_settings_setstr(global_settings.get(), "synth.chorus.active", "no");
fluid_settings_setstr(global_settings.get(), "synth.reverb.active", "no");
fluid_settings_setstr(global_settings.get(), "synth.chorus.active", "no");
#endif

// Fluidsynth 1.x does not support VIO API for soundfonts
// Fluidsynth 1.x does not support VIO API for soundfonts
#if defined(HAVE_FLUIDSYNTH) && FLUIDSYNTH_VERSION_MAJOR > 1
// owned by fluid_settings
global_loader = new_fluid_defsfloader(global_settings.get());
fluid_sfloader_set_callbacks(global_loader,
vio_open, vio_read, vio_seek, vio_tell, vio_close);
// owned by fluid_settings
global_loader = new_fluid_defsfloader(global_settings.get());
fluid_sfloader_set_callbacks(global_loader,
vio_open, vio_read, vio_seek, vio_tell, vio_close);
#endif
}

global_synth.reset(create_synth(error_message));
if (!global_synth) {
global_synth.reset(create_synth(error_message));
if (!global_synth) {
return false;
}
return false;
}

init = true;

return init;
}

void FluidSynthDecoder::ResetState() {
once = false;
init = false;

global_synth.reset();
global_settings.reset();
}

void FluidSynthDecoder::SetSoundfont(StringView sf) {
preferred_soundfont = ToString(sf);
}
Expand Down
1 change: 1 addition & 0 deletions src/decoder_fluidsynth.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class FluidSynthDecoder : public MidiDecoder {
~FluidSynthDecoder() override;

static bool Initialize(std::string& error_message);
static void ResetState();

/**
* Sets the name of the preferred soundfont.
Expand Down
26 changes: 20 additions & 6 deletions src/decoder_wildmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
#define WILDMIDI_OPTS 0

static void WildMidiDecoder_deinit() {
WildMidi_Shutdown();
if (init) {
WildMidi_Shutdown();
init = false;
}
}

#if LIBWILDMIDI_VERSION >= 1027 // at least 0.4.3
Expand Down Expand Up @@ -71,6 +74,11 @@ static struct _WM_VIO vio = {
};
#endif

namespace {
bool once = false;
bool init = false;
}

WildMidiDecoder::~WildMidiDecoder() {
if (handle)
WildMidi_Close(handle);
Expand All @@ -80,10 +88,7 @@ bool WildMidiDecoder::Initialize(std::string& error_message) {
std::string config_file;
bool found = false;

static bool init = false;
static bool once = false;

// only initialize once
// only initialize once until a new game starts
if (once)
return init;
once = true;
Expand Down Expand Up @@ -289,11 +294,20 @@ bool WildMidiDecoder::Initialize(std::string& error_message) {
#endif

// setup deinitialization
atexit(WildMidiDecoder_deinit);
static bool atexit_once = false;
if (!atexit_once) {
atexit_once = true;
atexit(WildMidiDecoder_deinit);
}

return true;
}

void WildMidiDecoder::ResetState() {
once = false;
WildMidiDecoder_deinit();
}

bool WildMidiDecoder::Open(std::vector<uint8_t>& data) {
// this should not happen
if (handle) {
Expand Down
1 change: 1 addition & 0 deletions src/decoder_wildmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class WildMidiDecoder : public MidiDecoder {
~WildMidiDecoder();

static bool Initialize(std::string& error_message);
static void ResetState();

// Audio Decoder interface
bool Open(std::vector<uint8_t>& data) override;
Expand Down
2 changes: 2 additions & 0 deletions src/scene_gamebrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <memory>
#include "options.h"
#include "scene_settings.h"
#include "audio_midi.h"
#include "audio_secache.h"
#include "cache.h"
#include "game_system.h"
Expand Down Expand Up @@ -49,6 +50,7 @@ void Scene_GameBrowser::Continue(SceneType /* prev_scene */) {

Cache::ClearAll();
AudioSeCache::Clear();
MidiDecoder::Reset();
lcf::Data::Clear();
Main_Data::Cleanup();

Expand Down

0 comments on commit 5bb2a26

Please sign in to comment.