0

我正在尝试获取 MIDI 序列的轨道数:

File file = new File(strSource);
Sequence sequence = MidiSystem.getSequence(file);
int numTracks = sequence.getTracks().length;

... 其中 strSource 是我的 .mid 文件的完整路径+文件名。numTracks 为 1,但 .mid 文件有 16 个音轨(正如我在另一个 MIDI 编辑器中打开它时看到的那样)。文件类型为 0。

我在某处读到 type-0 文件不能为同一频道包含多个轨道。在这种情况下,所有轨道都被强制为单个轨道。那是对的吗?我怎样才能避免这种情况?

4

3 回答 3

0

我编写了一个小函数,将 Type # 0 序列转换为 Type # 1 序列

/**
 * Make multiple tracks from file0 track
 * @param in : Sequence with single track
 * @return Multiple track sequence
 */
private Sequence extractFile0Tracks (Sequence in) throws InvalidMidiDataException
{
    Track inTrack = in.getTracks()[0];
    HashMap<Integer, ArrayList<MidiEvent>> msgMap = new HashMap<>();

    // Distribute events per channel to ArrayList map
    for (int i = 0; i < inTrack.size(); i++)
    {
        MidiEvent event = inTrack.get(i);
        MidiMessage message = event.getMessage();
        if (message instanceof ShortMessage)
        {
            ShortMessage sm = (ShortMessage) message;
            int channel = sm.getChannel() + 1;
            ArrayList<MidiEvent> msgList = msgMap.computeIfAbsent(channel, k -> new ArrayList<>());
            msgList.add(event);
        }
    }

    // Create sequence with multiple tracks
    Sequence newSeq = new Sequence(in.getDivisionType(), in.getResolution());
    for (ArrayList<MidiEvent> msgList : msgMap.values())
    {
        Track tr = newSeq.createTrack();
        for (MidiEvent m1 : msgList)
            tr.add(m1);
    }

    return newSeq;
}
于 2017-10-10T17:48:59.010 回答
0

我用十六进制工具查看了文件......它实际上只有一个轨道。

另一个编辑器自己创建多个轨道。它似乎在搜索程序更改消息,然后将事件放入新轨道。

于 2017-10-10T13:26:07.610 回答
0

看来你是对的,type-0 文件在一个文件中包含多个轨道。 在这里你有一些信息。

无法从类型 0 文件中提取每个单独的轨道。

检查 MIDI 文件类型,如果外部 MIDI 编辑器可以检测到多个轨道,它可以是类型 1 或类型 2 文件,即使扩展名不匹配。

于 2017-10-10T10:14:23.740 回答