Java从MIDI键盘获取输入

标签 java input keyboard midi javasound

我用java设计了自己的合成器,现在想将它与midi键盘连接。我的下面的类(class)搜索所有具有发射器的 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 - getting data from piano? .

还有这个:http://www.jsresources.org/examples/MidiInDump.html

对于我想要的东西来说,接口(interface) Sequencer 看起来也太复杂了。

最佳答案

我发现 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 Controller ),在创建 MidiHandler 实例后,代码正确地打印出“midi returned”。

希望这有帮助!

关于Java从MIDI键盘获取输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61787140/

相关文章:

java - 无法从内部 Action 到达现场

Javascript填充输入值

c++ - 在 C++ 中处理 fscanf 等效项的更好方法

java - 使用用户输入创建二维数组并查找特定列的总和

command-line - Xfce 4 中是否有用于键盘快捷键的命令列表?

c# - XNA 在 PC 中显示 xbox 屏幕键盘

ios - 无法在 iOS 9 上选择 Cordova 应用程序输入字段

java - 在LinkedList中使用long类型id

java - org.hibernate.id.IdentifierGenerationException : "attempted to assign id from null one-to-one property"

java - 我可以为 complexType 和元素指定相同的名称吗 - XSD 标准