1

我需要从 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() 方法返回一个字节数组!如何将其转换为正常的人类形式,即整数?我读过它以这样的格式存储:“tt tt tt”,但是整个大/小端,有符号/无符号和可变长度的东西让它太混乱了。

4

2 回答 2

7

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;
于 2014-04-01T23:09:58.873 回答
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 文件,并且与其他元事件一样,不应通过线路实时传输。另一方面,使您感到困惑的数据字节描述适用于无线协议。

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

于 2017-08-08T11:43:33.503 回答