Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Midi: Properly shutdown and reinitialize #3092

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7269d32 breaks compilation with for platforms libretro, psvita, sdl and switch when compiling audio.o because they include audio_generic.h. Since this commit, said header includes audio_generic_midiout.h which does not provide a definition for AudioDecoderMidi itself.
This used to be no problem because audio_generic_midiout.h was only included from audio_generic.cpp which also includes the missing header.

The fix is to include audio_decoder_midi.h either in audio_generic.h or in audio_generic_midiout.h.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ Header mess :/. Thanks for testing this!

#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 @@ -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
Loading