如何从MetaMessage.getData()返回的字节数组中获取整数值?

时间:2014-04-01 22:44:55

标签: java int bytearray midi javax.sound.midi

我需要从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”,但整个大/小端,有符号/无符号和可变长度的东西使它太混乱了。

2 个答案:

答案 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文件,并且像其他元事件一样不应该通过电线实时传输。另一方面,令您困惑的数据字节描述适用于线上协议。

因此,对此主题的原始答案是正确的。