使用 javax.sound.midi 接收 midi 输入

Posted

技术标签:

【中文标题】使用 javax.sound.midi 接收 midi 输入【英文标题】:Receive midi input with javax.sound.midi 【发布时间】:2018-06-24 20:00:34 【问题描述】:

我想要一个程序,当它得到一个 midi 输入时,它可以做一些事情。

例如,当我单击控制器上的按钮 1 时,它应该打印“You clicked btn 1”,当我单击按钮 2 时,它应该打印“You clicked btn 2”。

我尝试使用 javax.sound.midi 库,但论坛或 youtube 上的所有示例都不起作用。

这对我来说最有效。它打印了我 PC 上的所有 Midi 设备,但没有收到任何东西。有人可以帮忙吗?

package de.snke.dev;

import javax.sound.midi.*;;



public class Main  extends Object implements Receiver

static MidiClass myMidi;

public static void main(String[] args) throws Exception 

    MidiDevice.Info[] info =
             MidiSystem.getMidiDeviceInfo();

            for (int i=0; i < info.length; i++) 
             System.out.println(i + ") " + info[i]);
             System.out.println("Name: " + info[i].getName());
             System.out.println("Description: " +
             info[i].getDescription());

             MidiDevice device =
            MidiSystem.getMidiDevice(info[i]);
             System.out.println("Device: " + device);
            



public void send(MidiMessage msg,
        long time) 
        System.out.println("Received message " + msg);
        

        public void close() 
        System.out.println("Closing");
        

编辑:现在我有

Sequencer           seq;
Transmitter         seqTrans;
Synthesizer         synth;
Receiver         synthRcvr;
try 
      seq     = MidiSystem.getSequencer();
      seqTrans = seq.getTransmitter();
      synth   = MidiSystem.getSynthesizer();
      synthRcvr = synth.getReceiver(); 
      seqTrans.setReceiver(synthRcvr);      
 catch (MidiUnavailableException e) 
      // handle or throw exception

我现在是否已连接到我的 APC Mini?对不起,我是初学者... 如果是,我现在如何读取 MIDI 输入?如果否,我需要改变什么?

【问题讨论】:

阅读documentation。 谢谢。我以前已经这样做了。我现在在线程中添加了一个新问题。 1.您的main 运行多长时间? 2.你希望哪个对象接收消息? 【参考方案1】:

解决办法是:

package de.snke.dev;

import javax.sound.midi.*;
import java.util.ArrayList;
import java.util.List;
import java.io.*;

public class Main


public void Main()

    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) 


    byte[] aMsg = msg.getMessage();
    // take the MidiMessage msg and store it in a byte array

    // msg.getLength() returns the length of the message in bytes
    for(int i=0;i<msg.getLength();i++)
        System.out.println(aMsg[i]);
        // aMsg[0] is something, velocity maybe? Not 100% sure.
        // aMsg[1] is the note value as an int. This is the important one.
        // aMsg[2] is pressed or not (0/100), it sends 100 when they key goes down,  
        // and 0 when the key is back up again. With a better keyboard it could maybe
        // send continuous values between then for how quickly it's pressed? 
        // I'm only using VMPK for testing on the go, so it's either 
        // clicked or not.
    
    System.out.println();

public void close() 


它是 2 线程解决方案结合起来打开所有 MIDI 设备并打印它们的速度、音符值和状态(点击或未点击)

别忘了!

你必须打电话

Main main = new Main();
main.Main();

在一个单独的类中启动 Main 类中的方法 Main。

【讨论】:

以上是关于使用 javax.sound.midi 接收 midi 输入的主要内容,如果未能解决你的问题,请参考以下文章

在播放时捕捉 MIDI 音符?

Java 中用于播放的硬件 MIDI 输出?

在 android (java) 中启用/禁用 MIDI 通道

从 Java 中的 Midi 文件中读取 Midi 消息 [重复]

Java Midi 定序器计时已关闭

你如何在 java 中访问 MIDI IN 流中的数据?