[英]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.