2009-09-28 57 views

回答

4

是的,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(); 
13

如果您想要通過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

+0

你也可以提供代碼來使用Track類嗎?謝謝。 – 2017-06-04 03:40:04

+1

@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