Java получает ввод с клавиатуры MIDI - PullRequest
10 голосов
/ 04 августа 2011

Я разработал свой собственный синтезатор в Java, и теперь я хочу подключить его с помощью MIDI-клавиатуры.Мой класс ниже ищет все устройства MIDI, которые имеют передатчики.Он успешно находит мою миди-клавиатуру.Я добавляю свои собственные приемники к каждому передатчику для каждого устройства, чтобы оно могло подобрать все возможное.Из прочтения всех справочных документов и java-документа я узнал, что передатчик отправляет MidiEvents получателю, который затем обрабатывает их методом send.Поэтому я написал свой собственный внутренний класс, реализующий Receiver, и просто использовал оператор println, чтобы проверить, было ли вообще что-либо обнаружено в методе send.Однако ничего не подобрано.Похоже, что сделать такую ​​простую вещь очень мало, и я просмотрел каждый файл справки, javadoc и форум.Я уверен, что это должно быть что-то действительно очевидное, что я как-то пропустил.

Мой синтезатор не следует путать с интерфейсом Synthesizer, и это не миди-инструмент.Он использует алгоритм синтеза и имеет метод воспроизведения.По сути, мне просто нужно, чтобы миди-клавиатура отправляла заметку о событии, которая вызовет метод воспроизведения.

import javax.sound.midi.*;
import java.util.ArrayList;
import java.util.List;
import java.io.*;
public class MidiHandler
{
    //ArrayList of MidiDevices
    private ArrayList<MidiDevice> devices = new ArrayList<MidiDevice>();

    public MidiHandler()
    {
        MidiDevice device;
        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
        for (int i = 0; i < infos.length; i++) {
            try {
                device = MidiSystem.getMidiDevice(infos[i]);
                //does the device have any transmitters?
                if (device.getTransmitters().size() > 0) {
                    //if it does, add it to the device list
                    System.out.println(infos[i] + ": " + device.getTransmitters().size());
                    devices.add(device);
                }
            } catch (MidiUnavailableException e) {}
        }
        //if any transmitting devices were found
        if(devices.size()>0) {
            //for each device
            for(int i = 0; i<devices.size(); i++) {
                try {
                    //get all transmitters
                    List<Transmitter> transmitters = devices.get(i).getTransmitters();
                    //and for each transmitter
                    for(int j = 0; j<transmitters.size();j++) {
                        //create a new receiver
                        transmitters.get(i).setReceiver(
                            //using my own MidiInputReceiver
                            new MidiInputReceiver(devices.get(i).getDeviceInfo().toString())
                        );
                    }
                    //open each device
                    devices.get(i).open();
                    //if code gets this far without throwing an exception
                    //print a success message
                    System.out.println(devices.get(i).getDeviceInfo()+" Was Opened");
                } catch (MidiUnavailableException e) {}
            }
        }
    }
    //tried to write my own class. I thought the send method handles an MidiEvents sent to it
    public class MidiInputReceiver implements Receiver {
        public String name;
        public MidiInputReceiver(String name) {
            this.name = name;
        }
        public void send(MidiMessage msg, long timeStamp) {
            System.out.println("midi received");
        }
        public void close() {}
    }
}

ПРИМЕЧАНИЕ: я уже видел это: Java MIDI - получение данных с фортепиано?1007 *.

и это: http://www.jsresources.org/examples/MidiInDump.html

Интерфейс Sequencer выглядел слишком сложным для того, что я тоже хочу.

Ответы [ 2 ]

14 голосов
/ 28 августа 2011

Я обнаружил, что MidiDevice getTransmitters (), похоже, возвращает список уже открытых передатчиков, а не передатчиков, которые доступны для открытия.Я считаю, что способ открыть новый передатчик через метод getTransmitter ().Я изменил ваш код, чтобы сделать это:

import javax.sound.midi.*;
import java.util.ArrayList;
import java.util.List;
import java.io.*;
    public class MidiHandler
{

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

            //get all transmitters
            List<Transmitter> transmitters = device.getTransmitters();
            //and for each transmitter

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

            Transmitter trans = device.getTransmitter();
            trans.setReceiver(new MidiInputReceiver(device.getDeviceInfo().toString()));

            //open each device
            device.open();
            //if code gets this far without throwing an exception
            //print a success message
            System.out.println(device.getDeviceInfo()+" Was Opened");


        } catch (MidiUnavailableException e) {}
    }


}
//tried to write my own class. I thought the send method handles an MidiEvents sent to it
public class MidiInputReceiver implements Receiver {
    public String name;
    public MidiInputReceiver(String name) {
        this.name = name;
    }
    public void send(MidiMessage msg, long timeStamp) {
        System.out.println("midi received");
    }
    public void close() {}
    }
}

На моем оборудовании (у меня подключен простой USB MIDI-контроллер), код правильно выводит «midi полученный» после создания экземпляра MidiHandler.

Надеюсь, это поможет!

2 голосов
/ 18 марта 2015

Я обнаружил, что вам необходимо открыть устройство перед вызовом setRecceiver (), в противном случае метод send () получателя будет вызван с любыми мусорными MIDI-данными с момента последнего запуска приложения.

device.open();

Transmitter trans = device.getTransmitter();    
// set new receiver after opening so that the input buffer will be flushed
trans.setReceiver(new MidiInputReceiver(device.getDeviceInfo().toString()));  
...