![](/img/trans.png)
[英]Java - Audible Lag with Custom MIDI Sequencer using PPQ Ticks for Timing
[英]Java Midi sequencer timing is off
這幾天一直在嘗試在Java中編寫一個節拍器進行練習。 我制作了一個簡單的 4/4 midi 節拍,該程序使用javax.sound.midi庫進行播放。
我的主要問題是音序器似乎在關閉時間播放第一拍。 如果我將序列設置為循環,這只會在第一個循環中發生。 附帶說明一下,如果我更改曲目的 bpm,它會在第一個循環后重置。
此外,我嘗試了多個 midi 文件,以防萬一我創建的 midi 文件出現問題,但我的所有測試都有相同的結果。
這是我處理 MIDI 播放的代碼:
public class MidiHandler
{
private Sequencer sequencer;
private Sequence seq;
private float newTempoFactor;
public MidiHandler()
{
try
{
sequencer = MidiSystem.getSequencer();
if (sequencer == null)
{
System.err.println("Sequencer not supported");
}
sequencer.open();
}
catch (MidiUnavailableException ex)
{
Logger.getLogger(MidiHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setAudioTrack(String filePath)
{
try
{
seq= MidiSystem.getSequence(new File(filePath));
sequencer.setSequence(seq);
}
catch (InvalidMidiDataException | IOException ex)
{
Logger.getLogger(MidiHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void playTrack(float bpm) throws InterruptedException
{
try
{
seq=editEvents();//editEvents() method pushes all midi events 100 ticks forward
sequencer.setSequence(seq);
}
catch (InvalidMidiDataException ex)
{
Logger.getLogger(MidiHandler.class.getName()).log(Level.SEVERE, null, ex);
}
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
//sequencer.setTempoInBPM(bpm);
newTempoFactor=bpm/120;
sequencer.setTempoFactor(newTempoFactor);//Default tempo is 120bpm --> Tempo factor =1
sequencer.setLoopStartPoint(100);//Shift the loop start/end by 100 ticks
sequencer.setLoopEndPoint(seq.getTickLength());
}
public Sequence editEvents()
{
Sequence seq= this.seq;
try
{
seq = MidiSystem.getSequence(new File("res//myTrack.mid"));
for (Track track : seq.getTracks())
{
for (int i=0; i < track.size(); i++)
{
MidiEvent event = track.get(i);
event.setTick(event.getTick()+100);
}
}
}
catch (InvalidMidiDataException | IOException ex)
{
Logger.getLogger(MidiHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return seq;
}
}
我的主 class
public class main
{
public static void main(String[] args)
{
try
{
MidiHandler mh = new MidiHandler();
mh.setAudioTrack("res//myTrack.mid");
mh.playTrack(120f);
}
catch (SecurityException | InterruptedException ex)
{
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
您的代碼看起來不錯。
不定時的初始節拍通常是由於連接的 Midi 設備(在我的情況下,當我使用外部 USB Midi 聲卡時)。 如果可以,請嘗試使用不同的 MidiDevice。
如果不能,解決方法是將創建的Sequence
的所有MidiEvents
移動 4 個節拍,然后使用Sequencer.setLoopEndPoint(long tick)
和Sequencer.setLoopStartPoint(long tick)
使循環從新的起點開始。
對於開始后的節奏變化,這是一個 JDK 錯誤。 解決方法是在Sequencer.setTempoInBPM()
Sequencer.start()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.