如何在迷笛序列中展望下一个事件



我们正在尝试使用javax.sound.midi为大学编写一个简单的吉他英雄克隆。

目前我们可以用音序器播放midi文件,并记录当前播放的midi事件。但是,我们希望显示即将到来的事件(更具体地说,是MIDI消息中指示注释的数据字节)。

我们目前正在使用一个音序器来播放声音和一个接收器,并将声音记录到控制台。但是,它会记录声音播放的确切时刻,而不是即将到来的声音。

在Sequencer类:

public void startSequencer() {
try {
sequencer.open();
Thread.sleep(2000);
sequencer.setTempoInBPM(BPM);
InputStream is = new BufferedInputStream(new FileInputStream(song));
sequencer.setSequence(is);
sequencer.getTransmitter().setReceiver(receiver);
sequencer.start();
while (sequencer.isRunning()) {
Thread.sleep(100);
}
sequencer.close();
System.out.println(receiver.getNoteOnAmount());
} catch (MidiUnavailableException | InterruptedException | IOException | InvalidMidiDataException e) {
throw new RuntimeException(e);
}
}

In Receiver class:

public void send(MidiMessage message, long timeStamp) {
//If the Status is NOTE_ON (144), process the note
if (message.getStatus() == 144) {
System,out.println(message.getMessage()[1]);
}

使用Sequencer.getSequence()Sequencer中检索Sequence

来自Midi文件的所有MidiEvents都存储在Sequence中的一个或多个Track实例中。MidiEvent是带有刻度位置的MidiMessageMidiEvents按刻度位置排序。

因此,在您的Receiver.send(MidiMessage)方法中,搜索轨道以找到与接收到的MidiMessage对应的MidiEvent

如果你只有一个轨道,并找到相应的MidiEvent在索引meIndex/tickmeTick,那么下一个MidiEvents要播放的是在meIndex+1,meIndex+2等。如果您有多个音轨,您还需要在其他音轨中搜索标记位置正好在meTick之后的MidiEvents

当然还有很多优化的空间(例如提前预处理Tracks),这样你就不用每次收到一个通知都花时间重新解析所有的track。

最新更新