博客研究

MIDI 导入 MuseScore 为什么乱糟糟?怎么解决

MIDI 文件存的是演奏,不是乐谱。看看这给 12 段吉他转谱带来了什么问题,以及导入前该设置些什么。

先说结论

MIDI 文件记录的是一次演奏:按了哪个键、什么时候按、按多重、按多久。它的音符没有升降号、声部、书面休止符或符杠,文件里也常常没有调号,所以 MuseScore 只能去猜,而音符偏离节拍网格时,它猜得最离谱。在 12 段吉他转谱上,我们最早的转换器一个调号也没写,还藏起了所有休止符;同样的音符先对齐到十六分音符网格、使用固定速度、在每条音轨写入调号,再交给 MuseScore Studio 4.7.5 的导入器,12 份里有 10 份调号正确,所有休止符也都显示了出来。MuseScore Studio 4 没有 MIDI 导入面板,所以这些修正要么写进 MIDI 文件,要么写进命令行用的选项文件。

MIDI 文件不存哪些信息?

读谱所需的大部分信息,它都不存。一个 MIDI 音符就是 0 到 127 之间的一个键号加一个力度值,在音符开始时发送一次,结束时再发送一次(MIDI 协会)。63 号音既是 D♯ 也是 E♭,该写哪个取决于调性,而音符本身并不说明。标准 MIDI 文件可以用元事件加入速度、拍号和调号,但声部、休止符、符杠和连音都没有标准的存放位置。休止符只是一段空隙,音长也只是 tick 数,而不是书面时值。

音频转 MIDI 工具还会带来第二个问题:它们的时间来自录音,音符很少正好落在拍点上。ScoreStarling 使用的 Spotify Basic Pitch 会按你给定的速度,把所有音符写进同一个 Electric Piano 1(电钢琴 1)声部,而且不写调号(note_creation.py)。要把它变成乐谱,就得为每个音符选定音名写法、书面时值、声部和谱表。每个转换器都得做这些选择,区别只在于做得好不好。

简单的转换器把 12 段吉他转谱弄成了什么样

我们最早的记谱环节,是一个基于 music21 库自己写的转换器。我们把公开数据集 GuitarSet 中 12 段录音经 Basic Pitch 转出的 MIDI 交给它,同时提供每段录音的速度,再由 Verovio 原样排版它写出的内容。逐一检查这 12 份乐谱,我们发现:

  • 所有乐谱都看不到休止符:music21 的 MusicXML 导出器默认用隐藏的休止符填补空隙(m21ToXml.py)。
  • 所有乐谱都没有调号。E 大调的曲子一个升号都没有;一段 C 大调伴奏的 431 个书面音符里,有 153 个带着多余的还原号(对应 421 个 MIDI 音符,有些被拆开后用延音线相连)。
  • 音名写法只看音符编号。MIDI 63 号音一律写成 E♭,即使在本该写 D♯ 的 E 大调里也是如此;在一首 G♭ 大调的曲子里,49 个调内音中有 30 个写错了。
  • 一行谱表上最多五个声部。音符的起点和终点各自对齐到最近的十六分音符,于是下一个音弹出时仍在振动的那根弦,就逼出了另一个声部,还配上了相应的附点和延音线。
  • 吉他被写成了钢琴:12 份乐谱中有 10 份用钢琴大谱表,另外 2 份用低音谱号,没有一份用吉他谱号,因为 Basic Pitch 把所有音符都标成了 Electric Piano(电钢琴)。

2026年10月7日,我们用同一批保存下来的 MIDI 文件重新运行了这个转换器,得到的数字完全一样。

问题不在音乐字体。Verovio 和它的 Leipzig 字体只是照着 MusicXML 画;错的是 MusicXML 本身。

前后对比:换用 MuseScore Studio 的导入器

我们先看了开源的替代方案:partitura 能处理调性、音名写法和声部,但没有量化器,也不写休止符;我们找到的其他研究工具,要么只支持钢琴,要么没有声明许可证、仅限非商业用途,或者尚未发布。于是我们把这项工作交给了 MuseScore Studio 4.7.5 的 MIDI 导入器,以独立程序的方式运行。同样的 12 段录音、同样的 Basic Pitch 音符、同样的给定速度,按下文的方法预处理,2026年10月2日在一台 Mac 上测得:

12 段 GuitarSet 转谱的前后对比
指标music21 转换器MuseScore 导入器
调号与标注一致0/1210/12
调内音写法与调性相悖2,703 个中 322 个3,213 个中 0 个
每个书面音符的变音记号数0.530.06
可见的休止符1,626 个中 0 个全部 988 个
单行谱表最多声部数52
所有 MIDI 音符均写出12/1212/12
4/4 拍、使用给定速度12/1212/12

两边的书面音符总数不同,是因为 MuseScore 用延音线跨拍、跨小节线连接音符的方式不一样。两个错的调都和标注差一个五度:G♭ 大调的曲子写成了 D♭ 大调,E 大调的写成了 B 大调。文件里没有我们估出的调时,MuseScore 自己猜的调只对了 5 份(2026年10月7日重测);正是把估计结果写进文件,才把它提高到 10 份。导入器处理每段录音用时 1.2–4.3 秒,平均 2.3 秒。

MuseScore 为什么会重新猜速度、拍号和调?

因为在它看来,没量化的 MIDI 像是一段现场演奏。导入器会检查落在拍点附近的音符,如果其中正好从拍点开始的不到 60%,它就把文件当作真人演奏(importmidi_quant.cpp)。接着它会运行自己的节拍追踪,选定拍号,并拉伸音符的时间去贴合它找到的拍子。MuseScore 的旧版手册说,这种模式是拿准确性换可读性,对没有对齐的文件默认开启。

调性另有一条规则。只要有任何一条非鼓音轨缺少调号,或者文件被判定为演奏,导入器就会根据音符估计调性(importmidi_key.cpp)。所以只在速度音轨里写调号是不够的,每条有音符的音轨都要有。直接导入 Basic Pitch 的原始 MIDI 时,我们看到拍号、速度和调全都被重新猜了一遍,哪怕已经把“真人演奏”选项设为 false。

导入前该怎么处理 MIDI?

能在 MIDI 文件里定下的记谱决定,就在 MuseScore 看到它之前定好。我们对每份转谱都会这样做:

  1. 使用一个固定的速度。ScoreStarling 会用你设定的 BPM,或从录音中检测出的速度;在 DAW(编曲软件)里,可以跟着节拍器录音,或者把工程速度调到与这条录音一致。
  2. 把每个音符的起点和终点都移到网格上,网格精度就是你想读到的最短时值。本文 10月2日的测试用的是 4/4 拍下的十六分音符。所有音符都在网格上时,MuseScore 会把文件当作写好的乐谱来读,而不是当作演奏。
  3. 把速度和拍号放在第一条音轨里,每条有音符的音轨都写上调号。我们用 music21 的 Krumhansl–Schmuckler 调性识别算法根据音符估计调性;如果你知道真正的调,就直接用它。
  4. 给每条音轨设上真实的乐器。MuseScore 会根据 General MIDI 音色来选择谱表和谱号:仍标为 Electric Piano 的吉他会被放到钢琴大谱表上,而设为尼龙弦吉他音色时,会用下方带 8 的高音谱号。
  5. 注意同音反复。如果同一个音在一个网格单位内弹了两下,对齐后两次起音会合并成一次;我们会把第二次往后挪一个三十二分音符。

MuseScore 导入该用哪些设置?

MuseScore Studio 4 没有可以设置这些选项的导入面板。它的手册说 MIDI 导入面板“目前尚未实现”,要求恢复它的 GitHub issue(#11918,2022年6月提出)在我们 2026年10月3日查看时仍未关闭。在软件里,唯一与量化有关的设置是导入 MIDI 文件时的最短音符时值,位于“首选项 → 导入”(Preferences → Import)。

导入器仍会从命令行里用 -M 传入的文件读取主要选项,手册的命令行页面附有一个示例。下面是 10月2日测试用的文件;现在 ScoreStarling 会把旋律写在一个声部里(VoiceCount 设为 0),并在第一小节是弱起小节时打开 RecognizePickupBar:

<?xml version="1.0" encoding="UTF-8"?>
<MidiOptions>
  <QuantValue>2</QuantValue>
  <VoiceCount>1</VoiceCount>
  <Duplets>false</Duplets>
  <Triplets>false</Triplets>
  <Quadruplets>false</Quadruplets>
  <Quintuplets>false</Quintuplets>
  <Septuplets>false</Septuplets>
  <Nonuplets>false</Nonuplets>
  <HumanPerformance>false</HumanPerformance>
  <MeasureCount2xLess>false</MeasureCount2xLess>
  <SplitStaff>false</SplitStaff>
  <ClefChanges>false</ClefChanges>
  <SimplifyDurations>true</SimplifyDurations>
  <ShowStaccato>false</ShowStaccato>
  <DottedNotes>true</DottedNotes>
  <RecognizePickupBar>false</RecognizePickupBar>
  <Swing>0</Swing>
</MidiOptions>

然后进行转换,输出文件用 MusicXML 扩展名:

mscore -M midi-import.xml -o score.musicxml performance.mid

程序的名称和位置因系统而异,Windows 上手册用的是 MuseScore4.exe。主要选项的作用如下:

我们的 MIDI 导入选项
选项取值作用
QuantValue2最短书面时值:十六分音符(1 为八分音符,3 为三十二分音符)
VoiceCount1每行谱表最多两个声部;声部数等于取值加一
Triplets 及其他连音选项false不识别连音,因为我们的网格里没有连音
HumanPerformancefalse不把文件当作现场演奏;只有音符都在网格上时,这样设置才成立
SplitStafffalse,钢琴为 true把钢琴声部按左右手分到两行谱表;对其他乐器,MuseScore 则会拆成单独的声部
SimplifyDurationstrue更少的休止符,更简单的时值
ClefChangesfalse谱表中途不插入小号的变换谱号
RecognizePickupBarfalse第一小节按完整小节处理
Swing0不检测摇摆节奏

如果你的音乐里有三连音,就不要对齐到直拍网格,并保持 Triplets 开启;MuseScore 识别三连音的效果如何,我们还没测过。在 MuseScore 3 里,这些设置都放在一个导入面板中,列名有 Max. voices、Search tuplets 和 Is human performance 等。

谱面更整洁,代价是什么?

会损失一些准确性,主要在音符时值上。以下是我们测得或已知的取舍:

  • MuseScore 把 26% 的音符写得比量化后的演奏更长,最多长出三个十六分音符,从来没有写短过;同时发声但长短不同的音符,也可能被写成同一个时值。在 ScoreStarling 里,播放和 MIDI 导出保留演奏的实际时间,不过旋律线会先清理一遍:同时弹下的几个音只留最强的那个,微弱的回声会去掉,持续的音在下一个音开始时结束。
  • 调性是根据音符估计的,12 份里错了 2 份,每次都差一个五度。带七个升号或降号的调,会写成对应的、只有五个升降号的等音调。
  • 10月2日这次吉他测试用的是直拍的十六分音符网格,表示不了三连音和摇摆节奏。ScoreStarling 转谱单件乐器或人声时依然如此,拍号从 4/4 开始;钢琴独奏则会跟随演奏的小节划分,可以选用 4/4、3/4、6/8 或 12/8。如果你自己准备文件,请写入真实的拍号。
  • MuseScore 会按自己的规则把钢琴和弦分给左右手,即使是两个音挨得很近的和弦,也可能被分到不同的谱表上。

其中一部分可以在导入后整理。工具 → 重组节奏(Tools → Regroup rhythms)会改写选中的段落,让音符按拍子分组,节奏本身不变。工具 → 用升号/降号重新拼写音高(Tools → Respell pitches with sharps / with flats)可以修改音名写法,不过手册说它是针对同一音高的音符设计的。调号错了,在导入前改 MIDI 文件,比导入后逐个改音符快得多。

MuseScore 能把 MP3 转成乐谱吗?

MuseScore Studio 不行:它能打开 MusicXML、MIDI 这类乐谱格式,但打不开音频。Muse Group 于 2026年8月17日在 MuseScore 网页平台上推出了 Audio-to-Score 测试版:支持钢琴独奏和原声吉他,MP3 文件最大 30 MB(约三分钟),免费,结果以 MSCZ 文件返回,供 MuseScore Studio 打开。我们还没有测试过。

另一条路就是本文讲的做法:先用音频转 MIDI 模型,再整理它的时间,最后交给 MuseScore 的导入器。ScoreStarling 转单件乐器或人声时就是这样,用的是 Basic Pitch;钢琴独奏则用一个钢琴模型,它转出的音符同时给出节拍和小节线;页面由 Verovio 绘制。现在,单音旋律会写在一行谱表的一个声部里,弹和弦的声部会把和弦保留在同一行谱表上,“乐谱设置 → 布局”还可以改变单声部录音的记谱方式。上面的测量数据来自 10月2日。10月4日,在旋律改为一次一个音、写在一行谱表上之后,我们重测了一遍:调号同样 12 份对了 10 份,3,158 个调内音里写法与调性相悖的为 0,357 个休止符全部显示。

你也可以在 ScoreStarling 里选择或拖入 MIDI 文件,直接得到可编辑的乐谱;鼓轨会被略去,整份乐谱只用一个拍号。录音只转写前五分钟,上传文件最大 100 MiB。PDF 免费,MusicXML 需要先解锁乐谱(一次性 15 积分);其余细节见技术规格(2026年10月7日核对)。工作台可以免费开始使用;注明日期的吉他和乐队测量结果,收录在《AI 扒谱到底有多准?我们实测了一下》一文中。

参考资料

  1. Summary of MIDI 1.0 Messages——MIDI Association
  2. Meta Message Types——mido 文档
  3. basic_pitch/note_creation.py——Spotify Basic Pitch,GitHub
  4. music21/musicxml/m21ToXml.py——music21,GitHub
  5. GuitarSet 1.1.0——Xi 等,Zenodo(CC BY 4.0)
  6. MIDI import——MuseScore 4 手册
  7. Restore MIDI import panel, issue #11918——MuseScore,GitHub
  8. importmidi_quant.cpp 和 importmidi_key.cpp——MuseScore 源代码,GitHub
  9. MIDI import——早期 MuseScore 手册(导入面板)
  10. Command line usage 及其中的MIDI 导入选项示例文件——MuseScore Studio 手册
  11. Preferences、File export、Regroup rhythms 和 Respell pitches——MuseScore Studio 手册
  12. Hear It, Play It: MuseScore Introduces New Smart Audio Recognition Features——Muse Group,2026年8月17日

常见问题

怎么把 MIDI 转成 MusicXML?

在 MuseScore Studio 里打开 MIDI 文件,选择“文件 → 导出”(File → Export),格式选 MusicXML,默认导出压缩的 .mxl。也可以在终端里运行 mscore -o score.musicxml file.mid,效果相同;加上 -M 还能传入一个选项文件,设置量化和声部。记得先把 MIDI 处理好,否则 MusicXML 里也会是同样的一团乱。

为什么 MIDI 导入后满是延音线和附点音符?

因为真人演奏的音符很少刚好在拍点上结束。对齐到很细的网格后,它们会跨过拍子和小节线,只能用延音线连起来;互相重叠的音符还会溢出到额外的声部里。把量化精度设为你想读到的最短时值,把导入器限制为最多两个声部,并让它简化时值;这样 MuseScore 会把部分音符写得稍长一点,让谱面更整洁。

为什么我以为是 E♭,MuseScore 却写成了 D♯?

MIDI 只记录 63 号音,不记录它该写成哪个音名,所以 MuseScore 会按调号来决定写法;某条音轨没有调号时,它就自己估计调性。导入前,在每条音轨里写好正确的调号。导入后,可以用“工具 → 用升号/降号重新拼写音高”(Tools → Respell pitches with sharps / with flats)修改选中的同音高音符。

MuseScore Studio 4 里还能用 MuseScore 3 的 MIDI 导入面板吗?

截至 2026年10月3日还不行:这个面板没有移植过来,要求恢复它的 GitHub issue #11918 也仍未关闭。MuseScore Studio 4 保留了一项针对导入 MIDI 的“最短音符”首选项,它的命令行也接受用 -M 传入选项文件,能覆盖原面板的主要设置。

ScoreStarling 的转谱结果能在 MuseScore 里打开吗?

可以。导出 MusicXML(.musicxml 或 .mxl),调号、音名写法、休止符和声部都会保留;如果只需要音符,导出 MIDI 也行。两者都需要先解锁乐谱,一次性花费 15 积分。ScoreStarling 可以免费开始使用;每份转谱结果都只是初稿,需要你用耳朵核对。

带来任何音乐带走一份乐谱