多轨 MIDI 文件如何工作?
how do multi-track midi files work?
我正在做一个分析 MIDI 文件并计算音阶的项目,但我碰壁了。
我可以找到一首单轨歌曲的所有音符(即只有一种乐器在演奏)但是我得到一个奇怪的多轨 MIDI 数字。
我制作了一个 MIDI 音符:88 个 C 音符、32 个 C#、16 个 D、68 G 和 36 E。当我将该 MIDI 文件通过我的分析器时,我得到:2 个 C 音符、2 个 C# 和 1 个 G
这是我将 MIDI 文件放入 ableton 后的样子:http://imgur.com/a/7pvPW
这是我的完整代码(抱歉,如果它真的很难看/不好,我是新手):http://pastebin.com/r7YkgqMB
很难找到有关如何构建 MIDI 文件的信息,但这是我的两个主要来源(也许是它们错了?):Source 1, Source 2
相关位:
for i in range(0, len(midi_bytes) - 3): # iterates through the midi (without head chunk)
# Looks for start of track chunk (MTrk)
if midi_bytes[i][1:3] + \
midi_bytes[i + 1][1:3] + \
midi_bytes[i + 2][1:3] + \
midi_bytes[i + 3][1:3] == "4D54726B":
# Found a track chunk
# How long is the chunk?
len_of_chunk = int(midi_bytes[i + 4][1:3] +
midi_bytes[i + 5][1:3] +
midi_bytes[i + 6][1:3] +
midi_bytes[i + 7][1:3], 16)
# iterates through that chunk (from 8 bytes after chunk start to length of chunk + 8 (from the 8 after))
for j in range(9, len_of_chunk + 8):
# Looks for keys
bit = int(midi_bytes[j][1:3], 16)
if midi_bytes[j - 1][1] == "8" and bit <= 127:
然后它检查 8(应该是停止音符命令)mod 12 之后的字节是什么(如果 = 0 那么它的 a c,= 1 是 c# 等)
您不能简单地搜索高半字节带有 8
的字节。音符关闭消息可以编码为速度为零的音符打开消息,并且在某些情况下可以省略状态字节(运行 状态)。此外,编码增量时间的字节也可以具有这样的值。
您必须正确解析 MIDI 文件。 (并阅读官方Standard MIDI Files (SMF) Specification。)
我以前不得不在非常基础的层面上处理 MIDI:header 读取和元数据提取、标准化事件识别、无法识别的事件处理 .. .
我写了一个非常简单的 JS 库 midi-parser-js 来完成它,我不得不说,由于这个有用的文档,它既快速又有趣:
https://github.com/colxi/midi-parser-js/wiki/MIDI-File-Format-Specifications
我希望它以帮助我的方式帮助你。
快速考虑:
我不知道 是你的特殊要求,但是,在我的特定情况下,经过一些研究,我选择 pre-process .mid 文件二进制 RAW 数据,并将其解析存储到更多'handy & usable' 数据结构:Objects 具有用于保存元数据的属性 -bpm、主动效果、activeinstrument...-,以及带有 Midi 事件列表的属性(数组))...
这样它允许我简单地将事件推送到数组中,而 musical-clock 模块只需要分析和安排 "events array items"...
我正在做一个分析 MIDI 文件并计算音阶的项目,但我碰壁了。
我可以找到一首单轨歌曲的所有音符(即只有一种乐器在演奏)但是我得到一个奇怪的多轨 MIDI 数字。
我制作了一个 MIDI 音符:88 个 C 音符、32 个 C#、16 个 D、68 G 和 36 E。当我将该 MIDI 文件通过我的分析器时,我得到:2 个 C 音符、2 个 C# 和 1 个 G
这是我将 MIDI 文件放入 ableton 后的样子:http://imgur.com/a/7pvPW
这是我的完整代码(抱歉,如果它真的很难看/不好,我是新手):http://pastebin.com/r7YkgqMB
很难找到有关如何构建 MIDI 文件的信息,但这是我的两个主要来源(也许是它们错了?):Source 1, Source 2
相关位:
for i in range(0, len(midi_bytes) - 3): # iterates through the midi (without head chunk)
# Looks for start of track chunk (MTrk)
if midi_bytes[i][1:3] + \
midi_bytes[i + 1][1:3] + \
midi_bytes[i + 2][1:3] + \
midi_bytes[i + 3][1:3] == "4D54726B":
# Found a track chunk
# How long is the chunk?
len_of_chunk = int(midi_bytes[i + 4][1:3] +
midi_bytes[i + 5][1:3] +
midi_bytes[i + 6][1:3] +
midi_bytes[i + 7][1:3], 16)
# iterates through that chunk (from 8 bytes after chunk start to length of chunk + 8 (from the 8 after))
for j in range(9, len_of_chunk + 8):
# Looks for keys
bit = int(midi_bytes[j][1:3], 16)
if midi_bytes[j - 1][1] == "8" and bit <= 127:
然后它检查 8(应该是停止音符命令)mod 12 之后的字节是什么(如果 = 0 那么它的 a c,= 1 是 c# 等)
您不能简单地搜索高半字节带有 8
的字节。音符关闭消息可以编码为速度为零的音符打开消息,并且在某些情况下可以省略状态字节(运行 状态)。此外,编码增量时间的字节也可以具有这样的值。
您必须正确解析 MIDI 文件。 (并阅读官方Standard MIDI Files (SMF) Specification。)
我以前不得不在非常基础的层面上处理 MIDI:header 读取和元数据提取、标准化事件识别、无法识别的事件处理 .. .
我写了一个非常简单的 JS 库 midi-parser-js 来完成它,我不得不说,由于这个有用的文档,它既快速又有趣: https://github.com/colxi/midi-parser-js/wiki/MIDI-File-Format-Specifications
我希望它以帮助我的方式帮助你。
快速考虑: 我不知道 是你的特殊要求,但是,在我的特定情况下,经过一些研究,我选择 pre-process .mid 文件二进制 RAW 数据,并将其解析存储到更多'handy & usable' 数据结构:Objects 具有用于保存元数据的属性 -bpm、主动效果、activeinstrument...-,以及带有 Midi 事件列表的属性(数组))... 这样它允许我简单地将事件推送到数组中,而 musical-clock 模块只需要分析和安排 "events array items"...