Java 从 MIDI 键盘获取输入
Posted
技术标签:
【中文标题】Java 从 MIDI 键盘获取输入【英文标题】:Java getting input from MIDI keyboard 【发布时间】:2011-10-19 17:56:24 【问题描述】:我已经用 java 设计了自己的合成器,现在我想将它与 MIDI 键盘连接。我下面的班级搜索所有具有发射器的 MIDI 设备。它成功地找到了我的 MIDI 键盘。我将自己的接收器添加到每个设备的每个发射器,以便它可以接收所有可能的信息。通过阅读所有帮助文档和 java 文档,我知道 Transmitter 将 MidiEvents 发送到 Receiver,然后使用 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 - getting data from piano?。
还有这个:http://www.jsresources.org/examples/MidiInDump.html
interface Sequencer 对于我想要的东西来说看起来也很复杂。
【问题讨论】:
【参考方案1】:我发现 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 控制器),代码在创建 MidiHandler 实例后正确打印出“midi received”。
希望这会有所帮助!
【讨论】:
非常感谢!这确实有效,而且代码也不那么复杂。【参考方案2】:我发现你必须在调用 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()));
【讨论】:
在添加接收器之前打开 deviced 很重要以上是关于Java 从 MIDI 键盘获取输入的主要内容,如果未能解决你的问题,请参考以下文章
从其他驱动程序获取输入流?图形输入板驱动程序,输出 Midi 以与 Web Midi API 一起使用