This pull request fixes Wine's MIDI synthesizer reset process to be the same as Windows'.
When playing Touhou Project games in MIDI BGM mode, the music playback becomes buggy when the BGM changes. The video below is an example of an anomaly that occurs when playing The Fantastic Tales from Tono after playing Crystallized Silver in Touhou 7. https://youtu.be/O69sndJ45Ag
Here's a correct example of The Fantastic Tales from Tono playback: https://youtu.be/XlFAQEbbNDg
Piano sound is clearly missing on Wine. This issue occurs due to an Wine's incorrect reset process for MIDI synthesizer.
When I ran FluidSynth on Windows and checked the log, I found that CC123 and CC121 were executed for each MIDI channel when switching songs. CC123 means All Notes Off, CC121 means Reset All Controllers.
-- v8: wineoss: Send All Notes Off and Reset Controllers.
From: Keigo Okamoto reimu@hakurei.win
--- dlls/winealsa.drv/alsamidi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c index fbc65bd95d1..efd35e6628c 100644 --- a/dlls/winealsa.drv/alsamidi.c +++ b/dlls/winealsa.drv/alsamidi.c @@ -945,9 +945,9 @@ static UINT midi_out_reset(WORD dev_id) for (chn = 0; chn < 16; chn++) { /* turn off every note */ - midi_out_data(dev_id, (MIDI_CTL_ALL_SOUNDS_OFF << 8) | MIDI_CMD_CONTROL | chn); - /* remove sustain on all channels */ - midi_out_data(dev_id, (MIDI_CTL_SUSTAIN << 8) | MIDI_CMD_CONTROL | chn); + midi_out_data(dev_id, (MIDI_CTL_ALL_NOTES_OFF << 8) | MIDI_CMD_CONTROL | chn); + /* resets controller settings */ + midi_out_data(dev_id, (MIDI_CTL_RESET_CONTROLLERS << 8) | MIDI_CMD_CONTROL | chn); } dests[dev_id].runningStatus = 0; /* FIXME: the LongData buffers must also be returned to the app */
From: Keigo Okamoto reimu@hakurei.win
--- dlls/winecoreaudio.drv/coremidi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c index 113d5d267b4..f087d69008e 100644 --- a/dlls/winecoreaudio.drv/coremidi.c +++ b/dlls/winecoreaudio.drv/coremidi.c @@ -899,8 +899,8 @@ static UINT midi_out_reset(WORD dev_id) { /* turn off every note */ MusicDeviceMIDIEvent(dests[dev_id].synth, 0xB0 | chn, 0x7B, 0, 0); - /* remove sustain on channel */ - MusicDeviceMIDIEvent(dests[dev_id].synth, 0xB0 | chn, 0x40, 0, 0); + /* resets controller settings */ + MusicDeviceMIDIEvent(dests[dev_id].synth, 0xB0 | chn, 0x79, 0, 0); } } else FIXME("MOD_MIDIPORT\n");
From: Keigo Okamoto reimu@hakurei.win
--- dlls/wineoss.drv/ossmidi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c index 99c140266b0..8013e20559f 100644 --- a/dlls/wineoss.drv/ossmidi.c +++ b/dlls/wineoss.drv/ossmidi.c @@ -1238,9 +1238,9 @@ static UINT midi_out_reset(WORD dev_id) for (chn = 0; chn < 16; chn++) { /* turn off every note */ - midi_out_data(dev_id, 0x7800 | MIDI_CTL_CHANGE | chn); - /* remove sustain on all channels */ - midi_out_data(dev_id, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn); + midi_out_data(dev_id, (0x7B << 8) | MIDI_CTL_CHANGE | chn); + /* resets controller settings */ + midi_out_data(dev_id, (0x79 << 8) | MIDI_CTL_CHANGE | chn); } dest->runningStatus = 0; /* FIXME: the LongData buffers must also be returned to the app */
On Mon Aug 25 06:31:00 2025 +0000, Huw Davies wrote:
Could you squash that final commit into the two commits before it (as appropriate)?
OK, I just fixed.
This merge request was approved by Huw Davies.