From 40359929757fa9d142de41ff4735dc429bd8dea1 Mon Sep 17 00:00:00 2001 From: Jonathan Campbell Date: Fri, 10 Jan 2025 18:35:31 -0800 Subject: [PATCH] MIDI synth (Fluidsynth): Add code to recognize Roland GS MASTER VOLUME sysex. Now PC-98 games can "fade out" the MIDI music using GS commands (Seiyoku Gakuen Seraphita) --- include/midi.h | 1 + src/gui/midi_synth.h | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/midi.h b/include/midi.h index 13c648fee..85a48cc03 100644 --- a/include/midi.h +++ b/include/midi.h @@ -58,6 +58,7 @@ struct DB_Midi { DB_Midi() {} }; +extern bool roland_gs_sysex; extern DB_Midi midi; #endif diff --git a/src/gui/midi_synth.h b/src/gui/midi_synth.h index dd5f945a6..0a7c4a78e 100644 --- a/src/gui/midi_synth.h +++ b/src/gui/midi_synth.h @@ -33,6 +33,7 @@ static MixerChannel *synthchan = NULL; static fluid_synth_t *synth_soft = NULL; static int synthsamplerate = 0; +static uint8_t master_volume = 128; static void synth_log(int level, #if !defined (FLUIDSYNTH_VERSION_MAJOR) || FLUIDSYNTH_VERSION_MAJOR >= 2 // Let version 2.x be the default @@ -61,6 +62,11 @@ static void synth_log(int level, static void synth_CallBack(Bitu len) { if (synth_soft != NULL) { fluid_synth_write_s16(synth_soft, (int)len, MixTemp, 0, 2, MixTemp, 1, 2); + if (master_volume < 128) { + for (unsigned int i=0;i < (len*2);i++) { + ((int16_t*)MixTemp)[i] = (int16_t)(((((int16_t*)MixTemp)[i]) * master_volume) >> 7); + } + } synthchan->AddSamples_s16(len,(int16_t *)MixTemp); } } @@ -82,6 +88,23 @@ private: void PlayEvent(uint8_t *msg, Bitu len) { uint8_t event = msg[0], channel, p1, p2; + if (roland_gs_sysex) { + if (msg[1] == 0x41/*Roland*/ && msg[3] == 0x42/*GS*/ && msg[4] == 0x12/*Send*/ && len >= 9) { + const uint32_t addr = + ((uint32_t)msg[5] << 16) + + ((uint32_t)msg[6] << 8) + + (uint32_t)msg[7]; + + if (addr == 0x400004) { /* MASTER VOLUME */ + /* Fluidsynth doesn't appear to support this message, so we have to handle it ourself. */ + master_volume = msg[8]; + if (master_volume >= 127) master_volume = 128; + LOG_MSG("MIDI synth: MASTER VOLUME %u",master_volume); + return; + } + } + } + switch (event) { case 0xf0: case 0xf7: @@ -92,6 +115,7 @@ private: LOG(LOG_MISC,LOG_DEBUG)("SYNTH: midi tick"); return; case 0xff: + master_volume = 128; LOG(LOG_MISC,LOG_DEBUG)("SYNTH: system reset"); fluid_synth_system_reset(synth_soft); return; @@ -224,6 +248,7 @@ public: sffile=sf; fsinfo="Sound font: "+sf; + master_volume = 128; synthchan = MIXER_AddChannel(synth_CallBack, (unsigned int)synthsamplerate, "SYNTH"); synthchan->Enable(false); isOpen = true;