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 Oct 21, 2023
1 parent 43ff4d3 commit 2edb217
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 35 deletions.
1 change: 0 additions & 1 deletion src/audio_generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <cstring>
#include <cassert>
#include <memory>
#include "audio_decoder_midi.h"
#include "audio_generic.h"
#include "output.h"

Expand Down
2 changes: 1 addition & 1 deletion src/audio_generic_midiout.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

#include <memory>
#include "system.h"
#include "audio_decoder_midi.h"

class AudioDecoderMidi;
namespace Filesystem_Stream {
class InputStream;
}
Expand Down
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 @@ -38,8 +38,16 @@
*/
#define WILDMIDI_OPTS 0

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

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 @@ -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 2edb217

Please sign in to comment.