我需要从midi文件中获取速度值。我发现,set_tempo命令的值为0x51,所以我有这段代码:
for (int i = 0; i < tracks[0].size(); i++) {
MidiEvent event = tracks[0].get(i);
MidiMessage message = event.getMessage();
if (message instanceof MetaMessage) {
MetaMessage mm = (MetaMessage) message;
if(mm.getType()==SET_TEMPO){
// now what?
mm.getData();
}
}
}
但方法getData()返回一个字节数组!如何将其转换为正常的人形,a.k.a。整数? 我已经读过它以这样的格式存储:“tt tt tt”,但整个大/小端,有符号/无符号和可变长度的东西使它太混乱了。
答案 0 :(得分:5)
Tempo 是一个3字节的大端整数,每分钟位数计算为
BPM = 60,000,000 / (tt tt tt)
byte[] data = mm.getData();
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff);
int bpm = 60000000 / tempo;
答案 1 :(得分:1)
我用:
mpq = ((data[0] & 0x7f) << 14) | ((data[1] & 0x7f) << 7) | (data[2] & 0x7f);
其中mpq
表示每季度音符的微秒或每拍的微秒。
这样做的原因是Midi消息在每个字节中仅使用7位来表示数据。还应注意,在Java
中,字节数据类型(其数据是数组)是有符号整数,只有7个数据位的空间。
自从发表这篇文章后,我得到了MIDI协会的以下回复:
参数编号(tttttt)是一个24位无符号整数,采用大端格式。
“Set tempo”是一个元事件,属于SMF规范。它仅适用于标准MIDI文件,并且像其他元事件一样不应该通过电线实时传输。另一方面,令您困惑的数据字节描述适用于线上协议。
因此,对此主题的原始答案是正确的。