Java MIDI-сообщение SysEx, поток застрял, возможная ошибка?

Когда я отправляю сообщения sysex в режиме реального времени с разными длинами в байтах один за другим, миди-поток застревает. Это работает отлично, если я придерживаюсь только одного байта, но у меня есть 2 разных сообщения sysex для доставки: одно для изменения параметров в реальном времени и одно для полного патча (резервного копирования).
Я написал пример тестового примера через javaFX, чтобы продемонстрировать это поведение.

import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;
import static javax.sound.midi.SysexMessage.SYSTEM_EXCLUSIVE;


public class MidiTestEnvironment extends Application {

    public static MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
    public static MidiDevice outputDevice;
    public static Receiver outputReceiver;
    public static final byte DEVICE_NUMBER = 76;

    @Override
    public void start(Stage primaryStage) {

        // Show output devices only. Replace the DEVICE_NUMBER constant with a working
        // output midi device number.
        printOutputDevices();

        // Set the output device and open it first, then set the receiver. 
        try {
            outputDevice = MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[DEVICE_NUMBER]);
            if (!(outputDevice.isOpen())){
                outputDevice.open();
            }
            outputReceiver = outputDevice.getReceiver();
            System.out.println("outputreciever: " + outputDevice.getDeviceInfo().getName());
        } catch (MidiUnavailableException ex) {
            Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Create a Button and send a Message to the defined Midi Out
        Button btn1 = new Button("Send Message 82 bytes !");
        btn1.setOnAction((ActionEvent event) -> {
            try {
                // sendControlMessage(7,50);
                sendSysexMessage(SysexJX8P_APN(), SysexJX8P_APN().length);
                System.out.println("Hello World!");
            } catch (InvalidMidiDataException ex) {
                Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
            }
        });

        // Create a Slider and send a Message to the defined Midi Out
        Slider sysexSlider = new Slider(0,127,0);
        sysexSlider.setMaxHeight(200);
        sysexSlider.setOrientation(Orientation.VERTICAL);

        sysexSlider.valueProperty().addListener((value,oldValue,newValue)->{
            try {
                sendSysexMessage(SysexJX8P_L1(20,newValue.byteValue()),10);
            } catch (InvalidMidiDataException ex) {
                Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
            }
        });

        // Cobble the gui together
        HBox root = new HBox();
        root.setSpacing(20);
        root.getChildren().addAll(btn1,sysexSlider);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    //-------------------------------------------------------------------------------------------------------------------------------
    //-- SETUP MIDI MESSAGES
    //-------------------------------------------------------------------------------------------------------------------------------

    public static void sendControlMessage(int controller, int value) throws MidiUnavailableException {
        ShortMessage controlMessage = new ShortMessage();
        try {
            controlMessage.setMessage(ShortMessage.CONTROL_CHANGE, controller, value);
        } catch (InvalidMidiDataException ex) {
           Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
        }
        outputReceiver.send(controlMessage, -1);
    }



    public static void sendSysexMessage(byte[] data, int length) throws InvalidMidiDataException {
        SysexMessage sysexMessage = new SysexMessage();
        try {
            sysexMessage.setMessage(data, length);
            outputReceiver.send(sysexMessage, -1);
        } catch (InvalidMidiDataException ex) {
            Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    //-------------------------------------------------------------------------------------------------------------------------------
    // DISPLAY OUTPUT DEVICES ONLY
    public static void printOutputDevices() {
        for (int i = 0; i < MidiSystem.getMidiDeviceInfo().length; i++) {
            try {
                if (MidiSystem.getMidiDevice(infos[i]).getMaxReceivers() == -1
                        && !MidiSystem.getMidiDevice(infos[i]).getDeviceInfo().getName().equals("Gervill")) 
                {
                    System.out.println(infos[i].getName() + " - " + infos[i].getDescription() + " | device Number: " + i);
                }
            } catch (MidiUnavailableException ex) {
                Logger.getLogger(MidiTestEnvironment.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    //-------------------------------------------------------------------------------------------------------------------------------
    //-- TEST SYSEX MESSAGES
    //-------------------------------------------------------------------------------------------------------------------------------
    public static final byte[] SysexJX8P_L1(int p_byteEight, byte v_byteNine) {
        byte[] sysexStringL1 = new byte[10];
        sysexStringL1[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF);
        sysexStringL1[1] = 0x41;
        sysexStringL1[2] = 0x36;
        sysexStringL1[3] = 0x00;
        sysexStringL1[4] = 0x21;
        sysexStringL1[5] = 0x20;
        sysexStringL1[6] = 0x01;
        sysexStringL1[7] = (byte) p_byteEight;
        sysexStringL1[8] = v_byteNine;
        sysexStringL1[9] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);
        return sysexStringL1;
    }

    public static final byte[] SysexJX8P_APN() {
        byte[] sysExStringAP = {(byte) (SYSTEM_EXCLUSIVE & 0xFF), 0x41, 0x35, 0x00, 0x21, 0x20, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
            0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
            0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
            0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
            0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF)};
        return sysExStringAP;
    }


}

0 ответов

У меня была аналогичная проблема, как с jdk 8, так и с jdk 13. Решена путем закрытия и открытия MIDI-устройства при передаче sysex:

midiout.open();
midiout.getReceiver().send(outMsg, timeStamp);
midiout.close();
Другие вопросы по тегам