You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java识别XG格式MIDI文件中的鼓点音轨及音符

XG格式MIDI识别与鼓点检测实现方案(Java javax.sound.midi场景)

1. 判断MIDI文件是否为XG格式

XG格式的核心判定依据是文件头部的系统专有消息(SysEx),标准XG初始化SysEx的固定前缀为 F0 43 10 4C 00 00 7E 00,结尾为 F7,遍历MIDI文件所有轨道的系统消息匹配该前缀即可完成判定。
示例代码:

import javax.sound.midi.*;

public boolean isXGFormat(Sequence sequence) {
    // XG标准初始化SysEx前缀
    byte[] XG_SYS_EX_HEADER = new byte[]{(byte)0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00};
    for (Track track : sequence.getTracks()) {
        for (int i = 0; i < track.size(); i++) {
            MidiMessage msg = track.get(i).getMessage();
            if (msg instanceof SysexMessage) {
                byte[] data = msg.getMessage();
                if (data.length >= XG_SYS_EX_HEADER.length) {
                    boolean isMatch = true;
                    for (int j = 0; j < XG_SYS_EX_HEADER.length; j++) {
                        if (data[j] != XG_SYS_EX_HEADER[j]) {
                            isMatch = false;
                            break;
                        }
                    }
                    if (isMatch) return true;
                }
            }
        }
    }
    return false;
}

2. XG鼓点音符检测逻辑

原有仅检测通道9的方案漏判,是因为XG标准除了默认的10号通道(Java中索引为9)为鼓组通道外,还支持用户自定义最多8个鼓组通道,正确的检测需要先标记所有鼓组通道,再判断Note ON事件所属通道:

第一步:预标记所有鼓组通道

  1. 初始化时默认通道9为鼓组通道
  2. 遍历所有MIDI事件,满足以下所有条件的通道也标记为鼓组通道:
    • 控制改变消息(Control Change)CC#0值为127
    • 控制改变消息CC#32值为0
    • 程序改变消息(Program Change)值在120~127区间

第二步:检测鼓点音符

所有属于已标记鼓组通道、且力度>0的Note ON消息,均为鼓点音符
示例代码:

// 初始化标记数组
boolean[] isDrumChannel = new boolean[16];
boolean[] cc0Flag = new boolean[16]; // 存储各通道CC#0=127的状态
boolean[] cc32Flag = new boolean[16]; // 存储各通道CC#32=0的状态
isDrumChannel[9] = true; // 默认通道9为鼓组通道

// 遍历所有事件更新鼓组通道标记
for (Track track : sequence.getTracks()) {
    for (int i = 0; i < track.size(); i++) {
        MidiMessage msg = track.get(i).getMessage();
        if (msg instanceof ShortMessage sm) {
            int channel = sm.getChannel();
            switch (sm.getCommand()) {
                case ShortMessage.CONTROL_CHANGE -> {
                    if (sm.getData1() == 0 && sm.getData2() == 127) cc0Flag[channel] = true;
                    if (sm.getData1() == 32 && sm.getData2() == 0) cc32Flag[channel] = true;
                }
                case ShortMessage.PROGRAM_CHANGE -> {
                    int progNum = sm.getData1();
                    if (cc0Flag[channel] && cc32Flag[channel] && progNum >=120 && progNum <=127) {
                        isDrumChannel[channel] = true;
                    }
                }
            }
        }
    }
}

// 鼓点判定方法
public boolean isDrumNote(ShortMessage sm) {
    return sm.getCommand() == ShortMessage.NOTE_ON
            && sm.getData2() > 0
            && isDrumChannel[sm.getChannel()];
}

注意事项

  • 上述逻辑仅适配标准XG格式MIDI,非规范自制XG文件可能需要额外适配
  • 判定SysEx时注意完整匹配前缀,避免将GM/GS格式的系统消息误判为XG

内容的提问来源于stack exchange,提问作者Invariant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 23:45:03