我從一臺連接到計算機的鋼琴上繼承了一個使用an old C++ dll to receive MIDI data的Java項目。Java MIDI - 從鋼琴獲取數據?
既然Java已經內置了對MIDI設備的支持,那麼我想擺脫傳統的C++ dll而只使用純Java。 Java是否支持從連接到計算機的鋼琴接收數據?我已經搜索谷歌的例子無濟於事。
我從一臺連接到計算機的鋼琴上繼承了一個使用an old C++ dll to receive MIDI data的Java項目。Java MIDI - 從鋼琴獲取數據?
既然Java已經內置了對MIDI設備的支持,那麼我想擺脫傳統的C++ dll而只使用純Java。 Java是否支持從連接到計算機的鋼琴接收數據?我已經搜索谷歌的例子無濟於事。
是的,JavaSound API可用於從MIDI設備讀取MIDI數據。
JFugue是一個用於音樂編程的Java API,使用JavaSound API,可以幫助簡化與JavaSound的交互。在JFugue 5.x中,示例代碼捕獲MIDI數據爲10秒,從一個MIDI設備如下:
MidiDevice device = /* specify a MIDI device */
MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device);
transmitter.listenForMillis(10000);
Sequence music = transmitter.getSequence();
您也可以啓動和停止監聽設備:
MidiDevice device = /* specify a MIDI device */
MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device);
transmitter.startListening();
// Do stuff
transmitter.stopListening();
Sequence music = transmitter.getSequence();
下面是一個純java的例子Listens to a MIDI port and dump the received event to the console。你應該可以運行。 :)
如果您想要通過Java(javax.sound.midi。*)只記錄MIDI api,這很容易完成。這不是複製和粘貼的代碼,但它可以幫助您開始編寫自己的MIDI錄音機,實際上這很容易。
第一步是定義您的輸入和輸出MidiDevice。所以首先你必須找到一個IO可能性列表,並製作一個GUI,你可以在其中爲你的MIDI錄音和回放選擇輸入和輸出設備。
Info[] infos = MidiSystem.getMidiDeviceInfo();
for(int i=0;i<infos.length;i++)
{
System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
}
所以有一個你的MIDI設備列表。接下來,您要選擇一個MIDI設備,例如,您可以選擇infos數組中的索引。
MidiDevice inputDevice = MidiSystem.getMidiDevice(infos[x]);
MidiDevice outputDevice = MidiSystem.getMidiDevice(infos[y]);
您還需要指定一些全局變量:音序器,發送器和接收器。
Sequencer sequencer = MidiSystem.getSequencer();
Transmitter transmitter;
Receiver receiver;
現在有一個記錄按鈕,你想使用。
// Open a connection to your input device
inputDevice.open();
// Open a connection to the default sequencer (as specified by MidiSystem)
sequencer.open();
// Get the transmitter class from your input device
transmitter = inputDevice.getTransmitter();
// Get the receiver class from your sequencer
receiver = sequencer.getReceiver();
// Bind the transmitter to the receiver so the receiver gets input from the transmitter
transmitter.setReceiver(receiver);
// Create a new sequence
Sequence seq = new Sequence(Sequence.PPQ, 24);
// And of course a track to record the input on
Track currentTrack = seq.createTrack();
// Do some sequencer settings
sequencer.setSequence(seq);
sequencer.setTickPosition(0);
sequencer.recordEnable(currentTrack, -1);
// And start recording
sequencer.startRecording();
當心,這個代碼可以拋出MidiUnavailableExceptions,你應該呼籲所有你在最後聲明中已經打開了的東西close方法。
但這只是代碼應該看起來像什麼的核心。只要調用方法sequencer.startRecording()
,它就會將所有內容記錄到序列seq
。
然後,您要停止錄製,並能夠將序列保存爲MIDI到文件或進行回放。例如,當您按下停止記錄按鈕或某物時,這可能是代碼。
// Stop recording
if(sequencer.isRecording())
{
// Tell sequencer to stop recording
sequencer.stopRecording();
// Retrieve the sequence containing the stuff you played on the MIDI instrument
Sequence tmp = sequencer.getSequence();
// Save to file
MidiSystem.write(tmp, 0, new File("MyMidiFile.mid"));
}
此外,軌道類(一個序列可以有多個軌道)包含實際的輸入數據,您可以通過get方法輕鬆訪問。 Track類由MidiEvents組成。例如,該軌道是:
MidiEvent 0: The C key is pressed
MidiEvent 1: The D key is pressed
MidiEvent 2: The C key of MidiEvent 0 is released
MidiEvent 3: The sustain pedal is pressed
etc...
而每的MidiEvent具有一定的時間戳,這是在MIDI蜱表達,由此可以很容易地通過增加或減少每秒滴答數改變速度。
這裏最難的問題是MidiEvents是用字節碼錶示的,因此你將不得不使用一個參考字節代碼表來告訴你哪個字節代表什麼動作。這應該讓你開始吧:http://www.onicos.com/staff/iz/formats/midi-event.html
你也可以提供代碼來使用Track類嗎?謝謝。 – 2017-06-04 03:40:04
@AliSharabiani你可以看到'Track'爲'List'。沒有更多的東西,[請參閱javax.sound.midi.Track上的這個Oracle Java文檔](https://docs.oracle.com/javase/7/docs/api/javax/sound/midi/Track。 HTML)。 –
Yeti
2017-06-04 10:43:52