diff --git a/CMakeLists.txt b/CMakeLists.txt index 688eb2d970..ecc7e73e49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -551,8 +551,8 @@ endif() if(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2") target_sources(${PROJECT_NAME} PRIVATE - src/platform/sdl/audio.cpp - src/platform/sdl/audio.h + src/platform/sdl/sdl_audio.cpp + src/platform/sdl/sdl_audio.h src/platform/sdl/sdl2_ui.cpp src/platform/sdl/sdl2_ui.h) target_compile_definitions(${PROJECT_NAME} PUBLIC USE_SDL=2) @@ -574,8 +574,8 @@ if(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2") endif() elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL1") target_sources(${PROJECT_NAME} PRIVATE - src/platform/sdl/audio.cpp - src/platform/sdl/audio.h + src/platform/sdl/sdl_audio.cpp + src/platform/sdl/sdl_audio.h src/platform/sdl/axis.h src/platform/sdl/sdl_ui.cpp src/platform/sdl/sdl_ui.h) @@ -668,8 +668,8 @@ elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "wii") src/platform/wii/clock.cpp src/platform/wii/clock.h src/platform/wii/input_buttons.cpp - src/platform/sdl/audio.cpp - src/platform/sdl/audio.h + src/platform/sdl/sdl_audio.cpp + src/platform/sdl/sdl_audio.h src/platform/sdl/axis.h src/platform/sdl/sdl_ui.cpp src/platform/sdl/sdl_ui.h) @@ -681,8 +681,8 @@ elseif(${PLAYER_TARGET_PLATFORM} STREQUAL "amigaos4") target_compile_definitions(${PROJECT_NAME} PUBLIC USE_SDL=1) target_include_directories(${PROJECT_NAME} PUBLIC ${SDL_INCLUDE_DIR}) target_sources(${PROJECT_NAME} PRIVATE - src/platform/sdl/audio.cpp - src/platform/sdl/audio.h + src/platform/sdl/sdl_audio.cpp + src/platform/sdl/sdl_audio.h src/platform/sdl/axis.h src/platform/sdl/sdl_ui.cpp src/platform/sdl/sdl_ui.h) @@ -753,8 +753,8 @@ endif() if(APPLE) target_sources(${PROJECT_NAME} PRIVATE - src/platform/macos/utils.mm - src/platform/macos/utils.h + src/platform/macos/macos_utils.mm + src/platform/macos/macos_utils.h src/platform/macos/midiout_device_coreaudio.cpp src/platform/macos/midiout_device_coreaudio.h) diff --git a/Makefile.am b/Makefile.am index 3c4246bd1b..11554f283b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -443,8 +443,8 @@ libeasyrpg_player_a_SOURCES = \ SOURCEFILES_SDL2 = \ src/platform/sdl/sdl2_ui.cpp \ src/platform/sdl/sdl2_ui.h \ - src/platform/sdl/audio.cpp \ - src/platform/sdl/audio.h + src/platform/sdl/sdl_audio.cpp \ + src/platform/sdl/sdl_audio.h if HAVE_SDL2 libeasyrpg_player_a_SOURCES += $(SOURCEFILES_SDL2) else @@ -454,8 +454,8 @@ endif SOURCEFILES_SDL1 = \ src/platform/sdl/sdl_ui.cpp \ src/platform/sdl/sdl_ui.h \ - src/platform/sdl/audio.cpp \ - src/platform/sdl/audio.h \ + src/platform/sdl/sdl_audio.cpp \ + src/platform/sdl/sdl_audio.h \ src/platform/sdl/axis.h if HAVE_SDL1 libeasyrpg_player_a_SOURCES += $(SOURCEFILES_SDL1) @@ -493,8 +493,8 @@ EXTRA_DIST += $(SOURCEFILES_ALSA) endif SOURCEFILES_MACOS = \ - src/platform/macos/utils.h \ - src/platform/macos/utils.mm \ + src/platform/macos/macos_utils.h \ + src/platform/macos/macos_utils.mm \ src/platform/macos/midiout_device_coreaudio.cpp \ src/platform/macos/midiout_device_coreaudio.h if MACOS diff --git a/src/audio_decoder_midi.cpp b/src/audio_decoder_midi.cpp index 6874c48e3d..31b773ede7 100755 --- a/src/audio_decoder_midi.cpp +++ b/src/audio_decoder_midi.cpp @@ -41,7 +41,7 @@ static const uint8_t midi_set_reg_param_upper = 0x6; static const uint8_t midi_control_volume = 0x7; static const uint8_t midi_event_control_change = 0xB; static const uint8_t midi_set_reg_param_lower = 0x26; -//static const uint8_t midi_control_all_sound_off = 0x78; +static const uint8_t midi_control_all_sound_off = 0x78; static const uint8_t midi_control_reset_all_controller = 0x79; //static const uint8_t midi_control_all_note_off = 0x7B; static const uint8_t midi_set_reg_param_number_lower = 0x64; @@ -57,11 +57,11 @@ static uint32_t midimsg_make(uint8_t event_type, uint8_t channel, uint8_t value1 /*static uint32_t midimsg_all_note_off(uint8_t channel) { return midimsg_make(midi_event_control_change, channel, midi_control_all_note_off, 0); -} +}*/ static uint32_t midimsg_all_sound_off(uint8_t channel) { return midimsg_make(midi_event_control_change, channel, midi_control_all_sound_off, 0); -}*/ +} static uint32_t midimsg_volume(uint8_t channel, uint8_t volume) { return midimsg_make(midi_event_control_change, channel, midi_control_volume, volume); @@ -87,6 +87,28 @@ static inline uint8_t midimsg_get_value2(uint32_t msg) { return (msg & 0xFF0000) >> 16; } +static bool midimsg_validate(uint32_t msg) { + // Do some very basic sanity checks on the messages as + // invalid messages can cause the underlying MIDI synth to crash. + uint8_t event_type = midimsg_get_event_type(msg); + uint8_t channel = midimsg_get_channel(msg); + uint8_t value1 = midimsg_get_value1(msg); + uint8_t value2 = midimsg_get_value2(msg); + + if ((event_type >= 0 && event_type < 64) || + (event_type >= 70 && event_type < 84) || + (event_type == 88) || + (event_type >= 91 && event_type < 96) || + (event_type >= 98 && event_type < 102)) + { + if (value1 >= 128) { + // These event types must have a value of 0-127 + return false; + } + } + return true; +} + AudioDecoderMidi::AudioDecoderMidi(std::unique_ptr mididec) : mididec(std::move(mididec)) { seq = std::make_unique(); @@ -357,7 +379,9 @@ void AudioDecoderMidi::midi_message(int, uint_least32_t message) { // Send the modified volume to midiout message = midimsg_volume(channel, static_cast(value2 * volume)); } - mididec->SendMidiMessage(message); + if (midimsg_validate(message)) { + mididec->SendMidiMessage(message); + } } void AudioDecoderMidi::sysex_message(int, const void* data, std::size_t size) { @@ -384,6 +408,11 @@ void AudioDecoderMidi::reset() { const unsigned char gm_reset[] = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 }; mididec->SendSysExMessage(gm_reset, sizeof(gm_reset)); + // SoundOff every channel: only necessary for synths like macOS which tend to get stuck + if (mididec->NeedsSoftReset()) { + SendMessageToAllChannels(midimsg_all_sound_off(0)); + } + // Set the Pitch bend range to 256 for (int channel = 0; channel < 16; channel++) { auto midi_msg = midimsg_make(midi_event_control_change, channel, midi_set_reg_param_number_upper, 0); diff --git a/src/audio_midi.h b/src/audio_midi.h index 88c5fd73ae..8f023bb88f 100644 --- a/src/audio_midi.h +++ b/src/audio_midi.h @@ -180,6 +180,16 @@ class MidiDecoder { return true; } + /* + * Does the sequencer need "sound off" messages sent to every channel between + * tracks? NOTE: enabling this can break smooth fade outs between tracks. + * + * @return true only if synth needs "sound off" messages between tracks. + */ + virtual bool NeedsSoftReset() { + return false; + } + /** * Attempts to initialize a Midi library for processing the Midi data. * diff --git a/src/decoder_fluidsynth.cpp b/src/decoder_fluidsynth.cpp index a4d6bf3c92..2c6506d023 100644 --- a/src/decoder_fluidsynth.cpp +++ b/src/decoder_fluidsynth.cpp @@ -347,4 +347,8 @@ fluid_synth_t *FluidSynthDecoder::GetSynthInstance() { } } +bool FluidSynthDecoder::NeedsSoftReset() { + return true; +} + #endif diff --git a/src/decoder_fluidsynth.h b/src/decoder_fluidsynth.h index a5e2896d8f..f0799413e3 100644 --- a/src/decoder_fluidsynth.h +++ b/src/decoder_fluidsynth.h @@ -69,6 +69,8 @@ class FluidSynthDecoder : public MidiDecoder { #endif }; + bool NeedsSoftReset() override; + private: #if defined(HAVE_FLUIDSYNTH) || defined(HAVE_FLUIDLITE) fluid_synth_t* GetSynthInstance(); diff --git a/src/main_data.cpp b/src/main_data.cpp index 8a57dd79ff..86d4a8cc31 100644 --- a/src/main_data.cpp +++ b/src/main_data.cpp @@ -49,7 +49,7 @@ # include #elif defined(__APPLE__) && TARGET_OS_OSX # include -# include "platform/macos/utils.h" +# include "platform/macos/macos_utils.h" #endif // Global variables. diff --git a/src/platform/macos/utils.h b/src/platform/macos/macos_utils.h similarity index 100% rename from src/platform/macos/utils.h rename to src/platform/macos/macos_utils.h diff --git a/src/platform/macos/utils.mm b/src/platform/macos/macos_utils.mm similarity index 97% rename from src/platform/macos/utils.mm rename to src/platform/macos/macos_utils.mm index 53ca53ea77..5f6745118f 100644 --- a/src/platform/macos/utils.mm +++ b/src/platform/macos/macos_utils.mm @@ -22,7 +22,7 @@ #ifdef __APPLE__ #import #include -#include "platform/macos/utils.h" +#include "platform/macos/macos_utils.h" bool MacOSUtils::IsAppBundle() { bool is_bundle = false; diff --git a/src/platform/macos/midiout_device_coreaudio.cpp b/src/platform/macos/midiout_device_coreaudio.cpp index 73c29adf22..98ee57b8d9 100644 --- a/src/platform/macos/midiout_device_coreaudio.cpp +++ b/src/platform/macos/midiout_device_coreaudio.cpp @@ -98,6 +98,10 @@ std::string CoreAudioMidiOutDevice::GetName() { return "CoreAudio MIDI"; } +bool CoreAudioMidiOutDevice::NeedsSoftReset() { + return true; +} + bool CoreAudioMidiOutDevice::IsInitialized() const { return works; } diff --git a/src/platform/macos/midiout_device_coreaudio.h b/src/platform/macos/midiout_device_coreaudio.h index e958eb6f03..dbcf40f5df 100644 --- a/src/platform/macos/midiout_device_coreaudio.h +++ b/src/platform/macos/midiout_device_coreaudio.h @@ -32,6 +32,7 @@ class CoreAudioMidiOutDevice : public MidiDecoder { void SendMidiMessage(uint32_t message) override; void SendSysExMessage(const uint8_t* data, size_t size) override; std::string GetName() override; + bool NeedsSoftReset() override; bool IsInitialized() const; private: diff --git a/src/platform/sdl/sdl2_ui.cpp b/src/platform/sdl/sdl2_ui.cpp index 97416c953a..f51d3b0942 100644 --- a/src/platform/sdl/sdl2_ui.cpp +++ b/src/platform/sdl/sdl2_ui.cpp @@ -42,10 +42,10 @@ #include "lcf/scope_guard.h" #ifdef SUPPORT_AUDIO -# include "audio.h" +# include "sdl_audio.h" # if defined(__APPLE__) && TARGET_OS_OSX -# include "platform/macos/utils.h" +# include "platform/macos/macos_utils.h" # endif diff --git a/src/platform/sdl/audio.cpp b/src/platform/sdl/sdl_audio.cpp similarity index 99% rename from src/platform/sdl/audio.cpp rename to src/platform/sdl/sdl_audio.cpp index ffab5f4a84..c543027881 100644 --- a/src/platform/sdl/audio.cpp +++ b/src/platform/sdl/sdl_audio.cpp @@ -30,7 +30,7 @@ # include #endif -#include "audio.h" +#include "sdl_audio.h" #include "output.h" using namespace std::chrono_literals; diff --git a/src/platform/sdl/audio.h b/src/platform/sdl/sdl_audio.h similarity index 100% rename from src/platform/sdl/audio.h rename to src/platform/sdl/sdl_audio.h diff --git a/src/platform/sdl/sdl_ui.cpp b/src/platform/sdl/sdl_ui.cpp index 1019fa7ea9..dc8cee1b42 100644 --- a/src/platform/sdl/sdl_ui.cpp +++ b/src/platform/sdl/sdl_ui.cpp @@ -33,7 +33,7 @@ #endif #ifdef SUPPORT_AUDIO -# include "audio.h" +# include "sdl_audio.h" AudioInterface& SdlUi::GetAudio() { return *audio_;