我正在使用一个实现Receiver的类实时从midi键盘读取MIDI信息,并输出播放的音符。
我按下音符时收到的唯一信息是MidiMessage和timeStamp。
我正在尝试将音符描绘成实际的钢琴乐谱,目前用户必须事先设定bpm。
因此,如果我知道速度为120bpm(例如),我如何使用timeStamps来确定按下音符的长度?
我假设我可以将timeStamps转换为刻度(ppq),然后我可以用它来计算时间。
非常感谢任何帮助。下面是我的Receiver类中的“发送”方法。
'firstStamp'和'secondStamp'变量只是输出音符的长度。我发布了一个音符时取出了timeStamp,并在按下它时减去了timeStamp。
@Override
public void send(MidiMessage message, long timeStamp) {
String strMessage = null;
if (firstStamp == 0) {
firstStamp = timeStamp;
secondStamp = timeStamp;
}
firstStamp = secondStamp;
secondStamp = timeStamp;
stampDif = (secondStamp - firstStamp);
if (message instanceof ShortMessage) {
strMessage = decodeMessage((ShortMessage) message, timeStamp);
} else if (message instanceof MetaMessage) {
strMessage = decodeMessage((MetaMessage) message);
} else if (message instanceof SysexMessage) {
strMessage = decodeMessage((SysexMessage) message);
} else {
strMessage = "other message" + message.getStatus();
}
r_out.println("Timestamp: " + timeStamp + " " + strMessage);
r_printStream.println("Timestamp: " + timeStamp + " " + strMessage);
}
答案 0 :(得分:2)
如果时间戳以毫秒为单位,那么您可以将其转换为这样的滴答:
long ticks = timestamp * bpm / (1000 * 60);
由于时间戳可能是从1970年1月1日开始的,所以你会得到一个很高的开始时间。所以如果你想让你的第一个“勾号”为0,你需要跟踪这是否是你第一次看到的事件。
if (tickOffset == -1) { // Using -1 as not initialized
tickOffset = ticks;
}
ticks = ticks - tickOffset;