[英]Read MIDI input stream from a live instrument
我正在尝试创建一种自动乐谱查看器,只是为了好玩,我最终会尝试将其与 raspberry pi 或其他东西集成到我的数码钢琴中,但这是另一回事了。 让我们专注于我当前的问题。
为了完成这项工作,我必须将来自我的钢琴的 MIDI 输入与代表我正在演奏的乐谱的 MIDI 文件进行比较。
因为我想实时比较两个 MIDI,所以我发现很难直接从我的钢琴上获得现场 MIDI。
我已经尝试读取 10 秒的 MIDI 并将所有内容写入文件并且它可以完美地工作,但是我找不到任何方法来在我的钢琴发送消息时接收某种回调。
这是我当前的测试代码(这很糟糕,我知道,但我现在正在测试)我基本上将 10 秒的 MIDI 从我的钢琴写入一个 .mid 文件,我也尝试使用 ControllerEventListener,但是它似乎不起作用。
import java.io.File;
import java.io.IOException;
import javax.sound.midi.ControllerEventListener;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiDevice.Info;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.sound.midi.Transmitter;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) throws Exception {
Info[] infos = MidiSystem.getMidiDeviceInfo();
for(int i = 0; i < infos.length; i++) {
System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
}
MidiDevice inputDevice = MidiSystem.getMidiDevice(infos[1]);
Sequencer sequencer = MidiSystem.getSequencer();
Receiver receiver;
Transmitter transmitter;
inputDevice.open();
sequencer.open();
transmitter = inputDevice.getTransmitter();
receiver = sequencer.getReceiver();
transmitter.setReceiver(receiver);
Sequence seq = new Sequence(Sequence.PPQ, 24);
Track currentTrack = seq.createTrack();
sequencer.setSequence(seq);
sequencer.setTickPosition(0);
sequencer.addControllerEventListener(new ControllerEventListener() {
@Override
public void controlChange(ShortMessage event) {
System.out.println("listener works");
}
}, new int[] {127});
sequencer.recordEnable(currentTrack, -1);
sequencer.startRecording();
new Timer(10000, e -> {
Sequence tmp = sequencer.getSequence();
sequencer.stopRecording();
try {
MidiSystem.write(tmp, 0, new File("midi.mid"));
} catch (IOException e1) {
e1.printStackTrace();
}
System.exit(0);
}).start();
}
}
如您所见,我尝试向 Sequencer 添加一个 ControllerEventListener,但在录制时监听事件似乎不起作用:
sequencer.addControllerEventListener(new ControllerEventListener() {
@Override
public void controlChange(ShortMessage event) {
System.out.println("listener works");
}
}, new int[] {127});
无论我多么努力,但我找不到任何可以帮助我的东西......有什么方法可以接收现场 MIDI 乐器上的事件?
每当从我的钢琴发送消息时,我找不到任何方法来接收某种回调。
如果您希望在 Note ON MidiMessage 从您的钢琴到达时得到实时通知,请使用自定义接收器。
...
transmitter = inputDevice.getTransmitter();
receiver = new MyReceiver();
transmitter.setReceiver(receiver);
...
private class MyReceiver implements Receiver
{
...
@Override
public void send(MidiMessage mm, long timeStamp)
{
if (mm instanceof ShortMessage sm && sm.getCommand() == ShortMessage.NOTE_ON)
{
// Do something with the NoteOn message, preferably in another thread
}
}
}
如果您希望 Sequencer 并行记录 MidiMessages 以创建 Sequence,请从 inputDevice 获取第二个发送器并将其连接到 Sequencer 的接收器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.