On Fri, 27 Oct 2023 11:10:45 GMT, Alec Su <[email protected]> wrote: > JVM attempts to reuse the buffer for sending MIDI out data when the buffer > size is enough. It use `dwBytesRecorded` in `MIDIHDR` structure to indicate > the actual size of the data. However, `midiOutLongMsg()` ignores > `dwBytesRecorded`, although it did not mentioned in the documentation. I've > tested on Windows 7, 10 and 11. All of them have the same behavior. > > The bug cannot be easily reproduced because some MIDI drivers filter out any > malformed MIDI data. The example code below create a special case to make > sure all MIDI data are legally when the bug is triggered. > > > import javax.sound.midi.*; > > public class MidiTest { > public static class RawMidiMessage extends MidiMessage { > public RawMidiMessage(byte[] data) { > super(data); > } > > @Override > public Object clone() { > return new RawMidiMessage(this.getMessage()); > } > } > > public static void main(String[] args) { > var deviceInfos = MidiSystem.getMidiDeviceInfo(); > for (var info : deviceInfos) { > try (MidiDevice device = MidiSystem.getMidiDevice(info)) { > if (device.getMaxReceivers() != 0) { > System.out.println("Open MIDI port: " + info.getName()); > device.open(); > Receiver receiver = device.getReceiver(); > // Send two sysex messages at once > receiver.send(new RawMidiMessage(new byte[]{ > (byte) 0xF0, 0x7D, 0x01, (byte) 0xF7, > (byte) 0xF0, 0x7D, 0x02, (byte) 0xF7 > }), -1); > // Send another sysex message > receiver.send(new RawMidiMessage(new byte[]{(byte) 0xF0, > 0x7D, 0x03, (byte) 0xF7}), -1); > } > } catch (MidiUnavailableException e) { > e.printStackTrace(); > } > } > } > } > > > The expected messages received should be the following three messages > > F0 7D 01 F7 > F0 7D 02 F7 > F0 7D 03 F7 > > > But acually four messages was received with the second message repeated twice. > > F0 7D 01 F7 > F0 7D 02 F7 > F0 7D 03 F7 > F0 7D 02 F7 > > > To resolve the issue, I add a new variable to backup the actual buffer size > and set `dwBufferLength` of `MIDIHDR` structure to the size of MIDI data. > After calling `midiOutLongMsg()`, I restore the original buffer size if the > buffer hasn't been freed due to an error. > > It seems that the patch may also resolve JDK-8250667. The extra bytes in the > s...
This pull request has now been integrated. Changeset: e47cf611 Author: Alec Su <[email protected]> Committer: Phil Race <[email protected]> URL: https://git.openjdk.org/jdk/commit/e47cf611c9490225e50a548787cbba66ab147058 Stats: 46 lines in 5 files changed: 20 ins; 0 del; 26 mod 8074211: javax.sound.midi: Error with send System Exclusive messages of different length 8250667: MIDI sysex over USB scrambled when reply length matches previous message Reviewed-by: prr ------------- PR: https://git.openjdk.org/jdk/pull/16399
