【问题标题】:How to get integer value from byte array returned by MetaMessage.getData()?如何从 MetaMessage.getData() 返回的字节数组中获取整数值?
【发布时间】:2014-05-12 23:06:07
【问题描述】:

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

【问题讨论】:

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


    【解决方案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 文件,并且与其他元事件一样,不应通过线路实时传输。另一方面,让您感到困惑的数据字节描述适用于无线协议。

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

    【讨论】:

    • 两种解决方案提供的结果不一样吗?如果是这样,我不明白您的解决方案有什么优势。
    • 结果将相差大约 4 倍。即使第一个结果除以 4,它也将与第二个结果相差 3%,具体取决于位模式和存在每个数据项中的符号位。对此进行测试的方法是检查以各种速度播放或录制的一段音乐的持续时间。
    • 这很奇怪。几年前,我实际上在我的学士论文中使用了公认的答案。在打印和评估与估计基本面相关的一些 midi 数据时,它提供了正确的结果。并且录音的长度也等于绘制和评估的 midi 信号。轨道长达几分钟,因此会立即注意到 4 倍的差异。如果你说的是真的,我能解释它的唯一方法是它只能在特定的速度值下观察到。对吗?
    • 差异可以从 0 到大约 3% 不等,具体取决于速度。如果您查看位模式,您可以解决它。 120 bpm 的节奏表示 500000 的 mpq。在二进制中是
    • 差异可以从 0 到大约 3% 不等,具体取决于速度。如果您查看位模式,您可以解决它。 120 bpm 的速度表示 500000 的 mpq。二进制是 001111010000100100000。如果将其分成三组,每组 7 位并转换为十进制,则得到 30 66 32。如果您的程序中有此速度并执行 System.out .println(data[0] + " " + data[1] + " " + data[2]);你会得到 30 66 32。我在 Midi 规范中找不到任何说明二进制变量应该有符号或无符号的内容,但看起来 Java 正在使用有符号变量。
    【解决方案2】:

    Tempo 是一个 3 字节的大端整数,Bits Per Minute 计算为
    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 2016-08-29
      相关资源
      最近更新 更多