2017-02-20 43 views
0

我正在尋找使用Javasound編寫簡單的MIDI驅動音頻音序器。在Javasound中播放多個樣本

我有多個樣本(每個MIDI音高一個)作爲(全局訪問)Map<MidiPitch,AudioInputStream>加載到內存中。

javax.sound.midi.Receiver自定義子類響應輸入的MIDI事件如下:

如果事件是音符上,獲得並播放剪輯如下:

Clip clip = AudioSystem.getClip(); 
clip.open(lookupAIS(pitch)); 
clip.start(); 

剪輯是那麼添加到全球可訪問的Map<MidiPitch,List<Clip>>,代表開始的剪輯,即其上的start()已被如上​​調用但尚未收到音符關事件的剪輯。

如果事件是註銷,的對應列表開始剪輯是從上面的地圖中獲得的。清單頭部的剪輯被刪除,並調用stop()close()

以上Receiver以通常的方式連接到MidiSystem.getSequencer(),那麼以下稱爲:

sequencer.setSequence(MidiSystem.getSequence(new File(myMidFile))) 
sequencer.open() 
sequencer.start() 

Thread.sleep(aLongTime()) 

sequencer.stop() 
sequencer.close() 

上述工作當驅動MIDI序列是一個緩慢的節奏,但在更高的節奏,簡單的標誌掛(即使是包含非常少量音符的音序)。

我的理解是clip.start()在Javaound API的幕後由一個單獨的線程運行。

任何人都可以提出爲什麼會發生這種情況嗎?這可能是同步問題嗎?

編輯:'掛',我的意思是一些筆記被卡住,儘管事實上日誌輸出報告,相應的'停止'方法已被調用。

編輯2:它看起來好像當第二次播放給定音符時掛起的第一個音符發生。即使MIDI序列是單聲道的,即前一個音符已停止,也會發生這種情況。

+0

「掛」是否意味着一些剪輯繼續播放?你能證明(例如,記錄)你的代碼實際上試圖停止該剪輯嗎? –

+0

@CL上面已闡明。 – NietzscheanAI

+0

嗯,我們不會玩猜謎遊戲只是發佈你的代碼你在每一步做什麼都是未知的 - 理論上一切正常 – gpasch

回答

1

您爲每個播放加載剪輯的方法將成爲可變延遲的重要來源。每次您調用此文件時,都會重新讀取該文件,並且在整個文件加載完成之前不會開始播放。

我建議預先加載所有剪輯並將其保存在內存中。當調用音符時,將剪輯光標設置爲零,然後播放:

clip[mapIndex].setFramePosition(0); 
clip[mapIndex].start(); 

這些剪輯應該已經打開。我將它們放入一個數組中,並使用「mapIndex」作爲選擇正確剪輯的合理方式,可以與您已經設置的映射一起使用。

您可能不需要「停止」或「關閉」剪輯,直到整個序列完成,除非剪輯非常長並且設計爲在進行中停止,或者如果它們正在播放循環。

這應該會大大改善。我不能說它是否能解決所有問題。cpu可能正在進行一些線程複用,並且偶爾在您當前的代碼中,剪輯在另一個線程上完成加載之前,將在一個線程上調用clip.close。