java Java从MIDI键盘获取输入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6937760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java getting input from MIDI keyboard
提问by Jonathan
I have designed my own synthesizer in java and I now want to connect it with a midi keyboard. My class below searches through all the midi devices that have transmitters. It successfully finds my midi keyboard. I add my own receivers to each transmitter for each device so that it should pick up everything possible. From reading all the help documents and java doc I know that a Transmitter sends MidiEvents to a Receiver which then handles them with the send method. So I wrote my own inner class implementing Receiver and just used a println statement to check if there was anything detected at all in the send method. However nothing is picked up at all. There seems to be very little help to do such a simple thing and I have looked at every help file, javadoc and forum. I'm sure it must be something really obvious I have somehow missed.
我已经用 Java 设计了我自己的合成器,现在我想将它与 MIDI 键盘连接。我在下面的班级搜索所有具有发射器的 midi 设备。它成功找到了我的 MIDI 键盘。我将自己的接收器添加到每个设备的每个发射器中,以便它可以接收所有可能的信息。通过阅读所有帮助文档和 java 文档,我知道 Transmitter 将 MidiEvents 发送到 Receiver,然后使用 send 方法处理它们。因此,我编写了自己的内部类实现 Receiver,并仅使用 println 语句来检查 send 方法中是否检测到任何内容。然而,什么都没有被拾取。做这么简单的事情似乎没有什么帮助,我已经查看了每个帮助文件、javadoc 和论坛。我敢肯定它一定是我不知何故错过的非常明显的东西。
My synthesizer should not be confused with the interface Synthesizer and it is not a midi instrument. It uses a synthesis algorithm and has a playback method. Basically I just need to get the midi keyboard sending a note on event which will invoke the playback method.
我的合成器不应该与界面合成器混淆,它不是 MIDI 乐器。它使用合成算法并具有播放方法。基本上,我只需要让 MIDI 键盘在将调用播放方法的事件上发送一个注释。
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() {}
}
}
NOTE: I have already seen this: Java MIDI - getting data from piano?.
注意:我已经看过这个:Java MIDI - 从钢琴获取数据?.
and this: http://www.jsresources.org/examples/MidiInDump.html
和这个:http: //www.jsresources.org/examples/MidiInDump.html
interface Sequencer looked way to complicated for what I want also.
界面 Sequencer 对于我想要的东西看起来也很复杂。
回答by sjlevine29
I've found that the MidiDevice getTransmitters() appears to return the list of currently already-opentransmitters, not transmitters that are availableto be opened. I believe the way to open a new transmitter is via the getTransmitter() method. I've modified your code to do this:
我发现,在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() {}
}
}
On my hardware (I have a simple USB MIDI controller plugged in), the code correctly prints out "midi received" after an instance of MidiHandler is created.
在我的硬件上(我插入了一个简单的 USB MIDI 控制器),在创建 MidiHandler 实例后,代码正确打印出“midi received”。
Hope this helps!
希望这可以帮助!
回答by Robert
I've found that you have to open the device before calling setRecceiver(), otherwise the receiver's send() method gets called with any garbage MIDI data from the last time you ran the application.
我发现您必须在调用 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()));