On Sun, 29 Oct 2023 14:29:45 GMT, Alec Su <d...@openjdk.org> 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 >> buf... > > Alec Su has updated the pull request incrementally with one additional commit > since the last revision: > > Code cleanup
> 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. This seems to be documented by Microsoft only in the most obscure fashion. If you look at the doc for midiOutPrepareHeader https://learn.microsoft.com/en-us/previous-versions/dd798477(v=vs.85) it says "Before calling the function, set the lpData, dwBufferLength, and dwFlags members of the [MIDIHDR](https://learn.microsoft.com/en-us/previous-versions/dd798449(v=vs.85)) structure" So no mention of dwBytesRecorded. WAVEHDR is a very similar struct to MIDIHDR and if you look at this WAVEHDR doc it says https://learn.microsoft.com/en-us/previous-versions/dd743837(v=vs.85) dwBytesRecorded When the header is used in input, specifies how much data is in the buffer. So I infer the same is true for MIDI Therefore dwBytesRecorded is only used for input and dwBufferLength is what's important for output. ------------- PR Comment: https://git.openjdk.org/jdk/pull/16399#issuecomment-1786077861