Java从MIDI键盘获取输入
我用 java 设计了自己的合成器,现在想将它与 midi 键盘连接。我的下面的课程搜索所有具有发射器的 MIDI 设备。它成功找到了我的 MIDI 键盘。我将自己的接收器添加到每个设备的每个发射器中,以便它能够接收所有可能的信号。通过阅读所有帮助文档和 java 文档,我知道发送器将 MidiEvents 发送到接收器,然后接收器使用 send 方法处理它们。因此,我编写了自己的内部类来实现 Receiver,并仅使用 println 语句来检查 send 方法中是否检测到任何内容。然而什么也没有被拾取。做这样一个简单的事情似乎没有什么帮助,我已经查看了每个帮助文件、javadoc 和论坛。我确信这一定是我不知何故错过的非常明显的事情。
我的合成器不应与界面合成器混淆,它不是 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() {}
}
}
笔记: 我已经看过这个:Java MIDI - 从钢琴获取数据?。
这是: http://www.jsresources.org/examples/MidiInDump.html
界面对于我想要的东西来说,Sequencer 看起来也太复杂了。
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.
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.
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?.
and this: http://www.jsresources.org/examples/MidiInDump.html
interface Sequencer looked way to complicated for what I want also.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现 MidiDevice getTransmitters() 似乎返回当前已打开发射器的列表,而不是可用打开的发射器。我相信打开新发射器的方法是通过 getTransmitter() 方法。我已经修改了您的代码来执行此操作:
在我的硬件上(我插入了一个简单的 USB MIDI 控制器),在创建 MidiHandler 实例后,代码正确打印出“midi returned”。
希望这有帮助!
I've found that the MidiDevice getTransmitters() appears to return the list of currently already-open transmitters, not transmitters that are available to be opened. I believe the way to open a new transmitter is via the getTransmitter() method. I've modified your code to do this:
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.
Hope this helps!
我发现您必须在调用 setRecceiver() 之前打开设备,否则接收器的 send() 方法将使用上次运行应用程序时的任何垃圾 MIDI 数据来调用。
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.