Midi device connection and latency

蹲街弑〆低调 提交于 2019-12-24 14:23:03

问题


I am currently programming a simple application that takes input from a midi device and outputs the corresponding sound. I have gotten everything to work now, but there is two problems: First of all, when i plug in a midi device AFTER the program has started or disconnect it while the program is running, it will not get recognized. Second of all, the latency is very high on OSX, Linux (Raspbian) and Windows alike. Does anyone know the solution to either of these issues? Here is what i have so far:

The MidiHandler class reads the input and synthesizes the sound

public class MidiHandler {
MidiDevice device;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
List<Transmitter> transmitters;
MidiInputReceiver reciever;

public MidiHandler() {

    for (int i = 0; i < infos.length; i++) {
        try {
            this.device = MidiSystem.getMidiDevice(this.infos[i]);
            // does the device have any transmitters?
            // if it does, add it to the device list
            System.out.println(this.infos[i]);

            // get all transmitters
            this.transmitters = this.device.getTransmitters();

            // using my own MidiInputReceiver
            this.reciever = new MidiInputReceiver(this.device
                    .getDeviceInfo().toString());
            // and for each transmitter
            for (int j = 0; j < this.transmitters.size(); j++) {
                // create a new receiver
                this.transmitters.get(j).setReceiver(this.reciever);
            }

            Transmitter trans = this.device.getTransmitter();
            trans.setReceiver(new MidiInputReceiver(this.device
                    .getDeviceInfo().toString()));
            this.device.open();
        } catch (MidiUnavailableException e) {
        }
    }

}

public void playNote(byte b) {
    reciever.playNote(b);
}

public void stopNote(byte b) {
    reciever.stopNote(b);
}

public void close() {
    for (int i = 0; i < this.transmitters.size(); ++i) {
        this.transmitters.get(i).close();
    }
    this.reciever.close();
    this.device.close();
}

public String getInfos() {
    String infos = "";
    for (int i = 0; i < this.infos.length; i++) {
        infos += "\n" + this.infos[i] + " ";
    }
    return infos;
}

// tried to write my own class. I thought the send method handles an
// MidiEvents sent to it
public class MidiInputReceiver implements Receiver {
    Synthesizer synth;
    MidiChannel[] mc;
    Instrument[] instr;
    int instrument;
    int channel;

    public MidiInputReceiver(String name) {
        try {
            patcher p = new patcher();
            this.instrument = p.getInstrument();
            this.channel = p.getChannel();
            this.synth = MidiSystem.getSynthesizer();
            this.synth.open();
            this.mc = synth.getChannels();
            instr = synth.getDefaultSoundbank().getInstruments();
            this.synth.loadInstrument(instr[1]);
            mc[this.channel].programChange(0, this.instrument);
        } catch (MidiUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void send(MidiMessage msg, long timeStamp) {
        /*
         * Use to display midi message
        for (int i = 0; i < msg.getMessage().length; i++) {
            System.out.print("[" + msg.getMessage()[i] + "] ");

        }

        System.out.println();
        */

        if (msg.getMessage()[0] == -112) {
            mc[this.channel].noteOn(msg.getMessage()[1],
                    msg.getMessage()[2] + 1000);
        }

        if (msg.getMessage()[0] == -128) {
            mc[this.channel].noteOff(msg.getMessage()[1],
                    msg.getMessage()[2] + 1000);
        }

    }

    public void playNote(byte b) {
        mc[this.channel].noteOn(b, 1000);
    }

    public void stopNote(byte b) {
        mc[this.channel].noteOff(b);
    }

    public void close() {
    }

}

The Shell class contains the main method

public class Shell {
private static MidiHandler midi;
AudioServer server;

private Shell() {
}

/**
 * The main method. Executes via BufferedReader, to communicate with the
 * user
 * 
 * @param args
 *            Command line parameter
 * @throws IOException
 *             IOExeption can occur
 */
public static void main(String[] args) throws IOException {

    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    execute(in);
}

/**
 * Method used for general interaction with the user. Utilizes a
 * BufferedReader to read inputs, then proceeds to analyze the input for
 * predefined commands
 * 
 * @param in
 *            The BufferedReader in use
 * @throws IOException
 * @throws ParseException
 */
private static void execute(BufferedReader in) throws IOException {

    boolean quit = false;
    while (!quit) {

        midi = new MidiHandler();
        System.out.print("midi> ");
        String input;
        input = in.readLine(); // read line
        if (input == null | input.isEmpty()) {
            break;
        } // No command given?

        // First character is always the command.
        char command = Character.toLowerCase(input.charAt(0));

        try {

            switch (command) {

            case 'n':
                midi = new MidiHandler();
                break;

            case 'c':
                midi.close();
                break;

            case 'p':
                midi.playNote((byte) 60);
                break;

            case 's':
                midi.stopNote((byte) 60);

            case 'q':
                midi.close();
                quit = true;
                System.exit(0);
                break;

            default:
                System.out.println("Unknown command");
                break;
            }

        } catch (NumberFormatException e) {
            System.out.println("Invalid parameter");
        }

    }

}

Any help would be greatly appreciated. Thanks in advance.

来源:https://stackoverflow.com/questions/29781646/midi-device-connection-and-latency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!