前言
本文提出了一个支持 Muse 乐谱语法的数据结构方案。该方案以 abcjs 的 abc 乐谱数据结构为基础进行了部分优化,并扩展支持了 Tab 谱(六线谱、四线谱)与简谱。
一、描述信息
乐谱的元信息包含标题、副标题和作者等字段,对应关系如下:
主标题
语法:T: 单身情歌 (第一个 T 字段)
字段:metaText.title副标题
语法:T: 演唱 林志炫 (第 n 个,n ≥ 2)
字段:metaText.subtitle作者
语法:C: 陈耀川
字段:metaText.composer当有多个
C字段出现时,所有作者信息在composer字段中以换行符分隔。
二、调号、拍号和速度
调号
语法:K: C
字段:key{
"acc": "", // 升降调(# / b)
"accidentals": [], // 忽略
"mode": "", // 忽略
"root": "C" // 调名
}拍号
语法:M: 3/8
字段:meter{
"type": "specified",
"value": [
{ "num": "3", "den": "8" }
]
}速度
语法:Q: 1/4=120 "Slowly"
字段:metaText.tempo{
"bpm": 120,
"duration": [0.25],
"postString": "Slowly"
}上面的例子表示:一分钟演奏 120 个四分音符,速度标记为 "Slowly"。
三、音符与和弦
完整数据结构
一个音符节点位于 staffs[i].voices[i] 数组中,其完整结构如下:
{
"chord": [
{
"name": "C/E", // 和弦名称,查询和弦表
"position": "" // 忽略
}
],
"duration": 0.0625, // 音长
"el_type": "note",
"pitches": [
{
"fret": 1, // 品数,或者 'x'
"string": 5, // 第几弦:{a:1, b:2, c:3, d:4, e:5, f:6}
"pitch": 2, // 简谱使用
"accidental": "sharp" // 升半音:sharp,降半音:flat
}
],
// 多个 pitches 时表示和声,需在同一谱线上绘制
"startBeam": true, // 连音符开始
"endBeam": true, // 连音符结束
"startSlur": [], // slur 开始
"endSlur": [], // slur 结束
"startTie": [], // tie 开始
"endTie": [], // tie 结束(与 startTie 配合使用)
"startTriplet": 0, // 连音开始标识
"endTriplet": true, // 连音结束标识
"tripletMultiplier": 0.6667, // 每个音的音长倍数
"decoration": ["staccato"] // 装饰音列表
}说明:
tie表示相同音高的延音线slur表示两个不同音高之间的连音线triplet表示三连音、n 连音等,在音长计算上较为特殊
3.1 音高
四线谱 / 六线谱(Tab 谱)
{
"fret": 1, // 品数,或者 'x'(表示不弹)
"string": 5 // 第几弦:{a:1, b:2, c:3, d:4, e:5, f:6}
}a对应谱线最上面的一根弦,以此类推。- 如果是扫弦或琶音,只需关注最上面和最下面的弦即可。
简谱
在 Muse 中,中央 C 代表简谱的 1,小写 c 代表高八度的 1,C' 表示低八度的 1,依此类推。
音从低到高的顺序与五线谱一致:
C'', C', C, c, c', c''各音名对应 pitch 字段的编码值:
{
"A": 5, "B": 6, "C": 0, "D": 1, "E": 2, "F": 3, "G": 4,
"a": 12, "b": 13, "c": 7, "d": 8, "e": 9, "f": 10, "g": 11
}八度推算规则:
C' = C(0) - 7 = -7c' = c(7) + 7 = 14- 依此类推……
变音记号
示例:^b1
| 符号 | 名称 | 含义 |
|---|---|---|
^ | sharp | 升半音 |
= | natural | 还原音 |
_ | flat | 降半音 |
^^ | double sharp | 升全音(暂不支持) |
3.2 音长
默认音长:L: 1/4
音长修饰符的含义:
| 写法 | 含义 |
|---|---|
/ 或 /2 | 默认音长的 1/2(0.5 倍) |
// | 默认音长的 1/4(0.25 倍) |
2 | 默认音长的 2 倍 |
> | 前付点:前音 ×3/2,后音 ×1/2 |
< | 后付点:前音缩短,后音延长 |
示例:
弹唱谱:c1/, c1/2, cx//, a2*2
简谱: A/, C//, c1弹唱谱需要表示把位,因此用
/表示倍减,*表示倍增。
音长计算公式:
3.3 和弦图
所有和弦(包括默认和弦)存储在全局的 gchords 和弦表中。若某和弦不在和弦表中,则仅绘制和弦名称文字即可。
语法:
%%gchord <和弦名>=<起始品数>;<第n弦品位>(手指),<第n-1弦品位>(手指),...<第1弦品位>(手指)
示例:%%gchord C=1;X,3,2,0,1,0其中,手指编号为可选项,X 代表和弦外音(不弹该弦)。
数据结构:
{
"name": "C",
"chord": [
[1, 0], [2, 1], [3, 0], [4, 2], [5, 3], [6, "X"]
],
// 每项格式:[品位, 手指],数组下标按弦从上到下(从粗到细)
// "X" 代表和弦外音
"position": 3, // 起始品数(可选,无此字段则不需绘制位置标记)
"bars": [
{ "from_string": 5, "to_string": 1, "fret": 1 }
]
// bars:大横按信息(扩展字段,无声明则不绘制)
// from_string:起始弦,to_string:结束弦,fret:相对 position 的品数
}3.4 装饰音
装饰音符号添加在音符前面。
示例:u[b1*2-e3/]
| 符号 | 名称 | 含义 |
|---|---|---|
. | staccato | 断音、切音 |
V | upstrum | 上扫弦 |
U | downstrum | 下扫弦 |
A | uparpeggio | 上琶音 |
B | downarpeggio | 下琶音 |
' | accent | 加重音 |
T | trill | 颤音 |
H | fermata | 延长音(停顿) |
P | pralltriller | 短颤音 |
3.5 倚音
倚音同样添加在音符前面,使用花括号包裹。
示例:{a1b1}[c2//d2//]
倚音的数据结构与普通音符完全相同:
{
"accidental": "sharp",
"duration": 0.5,
"el_type": "note",
"pitch": 12,
"fret": 1,
"string": 1
}3.6 连音(二连音、三连音、n 连音)
语法:
简单连音:(n
示例:(2aC1
复杂连音:(p:q:r
示例:(3:2:4G2A2B1数据字段:
| 字段 | 含义 |
|---|---|
startTriplet | 连音开始标识 |
endTriplet | 连音结束标识 |
tripletMultiplier | 每个音的音长倍数 |
3.7 休止符
表示符号:z 和 Z,音长写法与音符相同。
z:普通休止符(rest)Z:多小节休止符(multimeasure),暂不支持
3.8 连音线(滑弦、敲弦、勾弦)
Tie(延音线) — 连接相同音高,表示延音:
ex-ex
[^b1*2-e3/]-S-[b2*5/2e4*5/2]Slur(连线) — 连接不同音高,表示连奏,可以嵌套:
((a3b2d2)b1)四、小节线与重复线
数据结构:
{
"el_type": "bar",
"type": "bar_thin", // bar 类型
"startEnding": "", // 重复段落数字及开始标志
"endEnding": "", // 重复结束标志
"barNumber": "" // 忽略
}常见小节线类型示意:
| 类型名 | 符号示意 | 说明 |
|---|---|---|
bar_thin | | | 普通小节线 |
bar_thin_thin | || | 双细线(段落分隔) |
bar_thin_thick | |] | 终止线(细线 + 粗线) |
bar_thick_thin | [| | 开始线(粗线 + 细线) |
bar_left_repeat | |: | 左重复线 |
bar_right_repeat | :| | 右重复线 |
bar_dbl_repeat | :: | 双重复线 |
bar_invisible | [:] | 隐形小节线(仅用于换行) |
五、歌词
英文歌词以空格断字,中文歌词以单字断字。
| 符号 | 含义 |
|---|---|
- | 英文单词断开(连字符) |
* | 跳过一个音符 |
~ | 连接两个字,对齐同一个音符 |
参考资料
- abcjs:用于渲染 abc 乐谱记谱法的 JavaScript 库。
- Muse 2.7 制谱软件帮助文档。
本文初发于2018年,当时在研究吉他谱在网页上渲染的相关技术,重新发表在这个新博客上,仅作记录。