Skip to content

Commit

Permalink
Merge pull request #3092 from Ghabry/audio/midi-reset
Browse files Browse the repository at this point in the history
Midi: Properly shutdown and reinitialize
  • Loading branch information
Ghabry authored Oct 23, 2023
2 parents a33e699 + 2edb217 commit 7741d74
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 67 deletions.
32 changes: 10 additions & 22 deletions src/audio_generic.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,21 @@
#include <cstring>
#include <cassert>
#include <memory>
#include "audio_decoder_midi.h"
#include "audio_generic.h"
#include "audio_generic_midiout.h"
#include "filefinder.h"
#include "output.h"

GenericAudio::BgmChannel GenericAudio::BGM_Channels[nr_of_bgm_channels];
GenericAudio::SeChannel GenericAudio::SE_Channels[nr_of_se_channels];
bool GenericAudio::BGM_PlayedOnceIndicator;

std::vector<int16_t> GenericAudio::sample_buffer = {};
std::vector<uint8_t> GenericAudio::scrap_buffer = {};
unsigned GenericAudio::scrap_buffer_size = 0;
std::vector<float> GenericAudio::mixer_buffer = {};

std::unique_ptr<GenericAudioMidiOut> GenericAudio::midi_thread;

GenericAudio::GenericAudio(const Game_ConfigAudio& cfg) : AudioInterface(cfg) {
int i = 0;
for (auto& BGM_Channel : BGM_Channels) {
BGM_Channel.id = i++;
BGM_Channel.decoder.reset();
BGM_Channel.instance = this;
}
i = 0;
for (auto& SE_Channel : SE_Channels) {
SE_Channel.id = i++;
SE_Channel.decoder.reset();
SE_Channel.instance = this;
}
BGM_PlayedOnceIndicator = false;
midi_thread.reset();
Expand Down Expand Up @@ -492,8 +480,8 @@ void GenericAudio::BgmChannel::Stop() {
stopped = true;
if (midi_out_used) {
midi_out_used = false;
midi_thread->GetMidiOut().Reset();
midi_thread->GetMidiOut().Pause();
instance->midi_thread->GetMidiOut().Reset();
instance->midi_thread->GetMidiOut().Pause();
} else if (decoder) {
decoder.reset();
}
Expand All @@ -503,16 +491,16 @@ void GenericAudio::BgmChannel::SetPaused(bool newPaused) {
paused = newPaused;
if (midi_out_used) {
if (newPaused) {
midi_thread->GetMidiOut().Pause();
instance->midi_thread->GetMidiOut().Pause();
} else {
midi_thread->GetMidiOut().Resume();
instance->midi_thread->GetMidiOut().Resume();
}
}
}

int GenericAudio::BgmChannel::GetTicks() const {
if (midi_out_used) {
return midi_thread->GetMidiOut().GetTicks();
return instance->midi_thread->GetMidiOut().GetTicks();
} else if (decoder) {
return decoder->GetTicks();
}
Expand All @@ -521,23 +509,23 @@ int GenericAudio::BgmChannel::GetTicks() const {

void GenericAudio::BgmChannel::SetFade(int fade) {
if (midi_out_used) {
midi_thread->GetMidiOut().SetFade(0, std::chrono::milliseconds(fade));
instance->midi_thread->GetMidiOut().SetFade(0, std::chrono::milliseconds(fade));
} else if (decoder) {
decoder->SetFade(0, std::chrono::milliseconds(fade));
}
}

void GenericAudio::BgmChannel::SetVolume(int volume) {
if (midi_out_used) {
midi_thread->GetMidiOut().SetVolume(volume);
instance->midi_thread->GetMidiOut().SetVolume(volume);
} else if (decoder) {
decoder->SetVolume(volume);
}
}

void GenericAudio::BgmChannel::SetPitch(int pitch) {
if (midi_out_used) {
midi_thread->GetMidiOut().SetPitch(pitch);
instance->midi_thread->GetMidiOut().SetPitch(pitch);
} else if (decoder) {
decoder->SetPitch(pitch);
}
Expand Down
23 changes: 12 additions & 11 deletions src/audio_generic.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@
#include "audio.h"
#include "audio_secache.h"
#include "audio_decoder_base.h"
#include "audio_generic_midiout.h"
#include <memory>

class GenericAudioMidiOut;

/**
* A software implementation for handling EasyRPG Audio utilizing the
* AudioDecoder for BGM and AudioSeCache for fast SE playback.
Expand Down Expand Up @@ -73,6 +72,7 @@ class GenericAudio : public AudioInterface {
struct BgmChannel {
int id;
std::unique_ptr<AudioDecoderBase> decoder;
GenericAudio* instance = nullptr;
bool paused;
bool stopped;
bool midi_out_used = false;
Expand All @@ -87,6 +87,7 @@ class GenericAudio : public AudioInterface {
struct SeChannel {
int id;
std::unique_ptr<AudioDecoderBase> decoder;
GenericAudio* instance = nullptr;
bool paused;
bool stopped;
};
Expand All @@ -103,17 +104,17 @@ class GenericAudio : public AudioInterface {
static constexpr unsigned nr_of_se_channels = 31;
static constexpr unsigned nr_of_bgm_channels = 2;

static BgmChannel BGM_Channels[nr_of_bgm_channels];
static SeChannel SE_Channels[nr_of_se_channels];
static bool BGM_PlayedOnceIndicator;
static bool Muted;
BgmChannel BGM_Channels[nr_of_bgm_channels];
SeChannel SE_Channels[nr_of_se_channels];
mutable bool BGM_PlayedOnceIndicator;
bool Muted;

static std::vector<int16_t> sample_buffer;
static std::vector<uint8_t> scrap_buffer;
static unsigned scrap_buffer_size;
static std::vector<float> mixer_buffer;
std::vector<int16_t> sample_buffer = {};
std::vector<uint8_t> scrap_buffer = {};
unsigned scrap_buffer_size = 0;
std::vector<float> mixer_buffer = {};

static std::unique_ptr<GenericAudioMidiOut> midi_thread;
std::unique_ptr<GenericAudioMidiOut> midi_thread;
};

#endif
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 @@ -50,6 +51,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 7741d74

Please sign in to comment.