节奏与时值
上一章介绍了音符的音名与音高。这一章给音符加入节奏:先用 @div、@dot 和 @dash 写出减时线、附点与增时线,再把它们缩写成日常使用的 /、. 和 -,接着用 @meter 设置拍号、用小节线划分小节,然后用 @tie 连接音符、表示延音。最后会进一步介绍减时线的分组、自动连接,以及需要精确控制时使用的 @beam 函数。
三个基本节奏函数
Section titled “三个基本节奏函数”jpFun 以四分音符为一个时值单位。本章讲解时值时,先把一个四分音符称为“一拍”;后面介绍拍号时,再区分不同拍号下的计拍单位。一个没有节奏修饰的普通音符占一个这样的时值单位;下面三个函数在这个基础上缩短或延长时值:
@div({content}, n=1, autobeam=true)@dot({content}, n=1)@dash()| 函数 | 作用 |
|---|---|
@div | 给 content 中的每个元素添加 n 条减时线;每多一条,时值变为一半 |
@dot | 给 content 添加 n 个附点;一个附点将时值延长为原来的 1.5 倍,两个延长为 1.75 倍。不过注意,content 只能有一个元素 |
@dash | 创建一根增时线,占一个四分音符的时值,并延续前面正在发声的音符 |
@div 和 @dot 的 n 都默认为 1。因此,@div(1) 是八分音符,@div(1, 2) 是十六分音符;@dot(1) 是附点四分音符,@dot(@div(1), 1) 则是附点八分音符。令减时线个数为 ,附点个数为 ,时长计算公式如下:
减时线与附点可以嵌套使用。无论在函数调用中先写 @div 还是先写 @dot,jpFun 都会先计算减时线,再计算附点;不过按简谱的阅读习惯,通常把减时线写在前面(里面)。
@dash 与前两个函数略有不同:它不接收内容,而是单独放在被延长的音符后面。一根增时线增加一拍,两根就增加两拍。
@note(1)
@div(@note(2), 1)
@dot(@note(3), 1)
@dot(@div(@note(4), 1), 1)
@note(5) @dash() @dash() @dash()dash 也可以被 div 和 dot 修饰。实际上,jpFun 中,减时线和附点可以加给任意视觉元素,非常自由:
@div({
1 @dot(@dash(), 3) 2
}, 1)
@div(@text("文本") $tr, 1)完整函数调用便于理解参数,但写旋律时会显得很长。三个基本节奏函数都有紧凑的简写:
| 函数调用 | 简写 | 含义 |
|---|---|---|
@div(1, 1) | 1/ | 八分音符 |
@div(1, 2) | 1// | 十六分音符 |
@dot(1, 1) | 1. | 附点四分音符 |
@dot(1, 2) | 1.. | 双附点四分音符 |
@dot(@div(1, 1), 1) | 1/. | 附点八分音符 |
1 @dash() @dash() | 1 -- | 将音符 1 延长两拍 |
/ 和 . 都写在要修饰的音符后面,可以连续写多个;- 本身就是一个独立的节奏位置。
1 2/ 3,// 4'/. #5. b6.. n7/./. - -. -/ 日常写谱时优先使用简写即可。需要修改 n、autobeam 等参数,或者要把一组音符作为整体处理时,再使用完整的函数调用。
有了音符的时值,还需要把它们组织成小节。@meter 设置拍号,@bar 创建小节线:
@meter(num, den, size=0.7em)@bar(type=0, length=1.25em)@meter 的 num 是拍号的分子,den 是分母,两者都必须是非负整数。正常拍号的分子、分母均为正数:分母表示用几分音符作为计数单位,分子表示每小节有几个这样的单位。比如 @meter(3, 4) 是 3/4 拍,每小节容纳三个四分音符;@meter(6, 8) 是 6/8 拍,每小节容纳六个八分音符。而分子或分母为 0 时表示散板(自由节奏)。
@meter(3, 4) 1 2 3 | 5 - - |||写出非散板 @meter 后,jpFun 会按小节边界检查累计时长;没有声明拍号或散板时,不会按某个默认拍号检查小节。
默认情况下,小节过长或不足会给出诊断提示;若在声明拍号前设置 @set(strict=true),则会报错并中断编译。曲首第一个小节允许不足,便于写弱起,但不能超长;曲尾即使没有小节线,也会检查最后一段的时长。
这里的 @set 用来修改默认设置,true 表示开启,false 表示关闭。这类只有两种状态的值叫作布尔值,不用加引号。设置如何生效,会在系统设置中详细介绍。
@bar 的第一个参数 type 是小节线的样式编号,0 到 5 分别对应下表中的六种样式,默认为 0(普通小节线)。因此,@bar() 等价于 @bar(0);也可以按名称传参,例如 @bar(type=3) 表示反复开始。length 控制线的高度,默认是 1.25em。常用样式都有简写:
| 函数调用 | 简写 | 含义 |
|---|---|---|
@bar(0) | | | 普通小节线 |
@bar(1) | || | 双竖线,两线等粗 |
@bar(2) | ||| | 终止线,左细右粗 |
@bar(3) | |: | 反复开始 |
@bar(4) | :| | 反复结束 |
@bar(5) | :|: | 结束前一反复段,同时开始后一反复段 |
反复小节线则不只是显示符号,还会影响播放顺序。关于“反复”,我们之后再说。
拍号不改变音符时值
Section titled “拍号不改变音符时值”设置拍号不会改变 1、1/ 等写法的时长。 即使设为 6/8,1 仍然是四分音符,1/ 才是八分音符,不能因为分母是 8 就省略减时线。
以四分音符为一个时值单位,令拍号的分子为 、分母为 ,小节时长 为:
因此,3/4 和 6/8 的小节总时长都是三个四分音符,但节拍组织不同:3/4 按三个四分音符拍自动连梁,6/8 则按两个附点四分音符大拍(三音一组)自动连梁。需要跨拍特殊分组时,也可以用 {1 2 3}/ 手动分组,详情见后。
连音线与延音
Section titled “连音线与延音”除了附点和增时线,还可以用 @tie 把音符连接起来。当同一音轨中同音高、时间连续的音符被连接时,它表示延音:后一个音符不重新发声,时值累加为一个持续的音。
@tie(label1, label2, ..., height=0)先在音符后用 @标签名 标记端点,再把标签传给 @tie。传入多个标签时,会依次连接相邻的端点;不传标签的 @tie() 则自动选取它前面最近的两个可标注对象。连接相邻音符时,把它紧接在第二个音符后面就很方便:
1@start 1/@end @tie(start, end)
1 1/@tie()这两组写法都会把两个八分音符合成一个持续一拍的音。与 1 - 通过增时线增加一拍不同,@tie 本身不占时值,而是连接已经写出的音符;因此也适合连接跨小节的同音。若连接的是不同音高,谱面上仍会画出连音线,但播放时不会把它们合成一个音。
用 height 调整弧高
Section titled “用 height 调整弧高”height 控制连音线的弧高,默认为 0(自动模式),负数也表示自动。通常无需设置:短连线低一些,长连线高一些,跨行时保持统一弧高。
需要手动调整时,传入正数即可指定固定弧高,例如 height=0.5em 或 height=10px。em 相对于调用处字号,数值越大,弧线越高。多条连线共用端点时,可以分别设置弧高来避免交叉:
1@x 2@y 3@z @tie(x,y) @tie(x,z) % 交叉了,很丑
1@x 2@y 3@z @tie(x,y,height=0.3em) @tie(x,z,height=0.6em)@tuplet 按比例改变一组音符的实际时值,并在上方绘制连音数与括线:
@tuplet({content}, normal)以 content 中最短的正时值为一个单位,normal(正整数) 指定整组最终占几个单位;它不是连音数,也不是拍数。 例如三个八分音符占两个八分音符的时长:
@meter(2, 4) @tuplet({1/ 2/ 3/}, 2) 4 | 5 - |||括线上显示 3,每个音占 1/3 拍,整组共一拍。连音数按时值单位计算,不一定等于音符个数,也可以写不等长的多连音:
@meter(2, 4) @tuplet({1/ 2 3}, 4) | 5 - |||三个音分别占 1、2、2 个八分音符单位,共五个;放进四个单位的时长里,括线上显示 5,整组共两拍,各音实际占 2/5、4/5、4/5 拍。
和 @tie 不同,@tuplet 故意设计为不允许跨谱面行,因为跨行的多连音不好看也不常见,用函数包裹更加精炼简短。关于和 @tie 的避让问题,请参考 反复与播放:跳房子与连音线等重叠问题。
自动连接减时线
Section titled “自动连接减时线”@div 的 autobeam 参数默认为 true,意味着不同的 @div 之间会尝试自动连接。jpFun 会根据当前拍号把同一音轨、相邻连续且处于同一拍内的减时音符连成一组(默认或 2/4、3/4、4/4、2/2 按四分音符一拍;3/8、6/8、9/8、12/8 等按三个分母音符组成的附点大拍;2/8 等按一个分母音符一拍):
1,/ 2,/ 3,/ 4,/ 5,/. 6,// 7,// 1/. |
1// 2// 3// 4// 5/ 6// 7// 1'/ 2'/ 2'//@tie() 3'/.如果不希望独立写出的减时线自动连接(或者希望全部手动连接),可以修改 div.autobeam 的值:
1/ 2/ 3/ 4/
1/ @div(2, 1, autobeam=false) 3/ 4/
@set(div.autobeam=false)
1/ 2/ 3/ 4/
被关闭的 div 会成为分组边界,左右两侧不会越过它继续连接。不过,autobeam=false 只会断开不同 div 之间的自动连接;写在同一个 @div({...}) 里的内容仍然保持一组——利用这个特性,我们可以实现手动分组↓
手动节拍切分
Section titled “手动节拍切分”@div 的 content 不只可以是一个音符,也可以是一段内容。用花括号把多个音符交给同一个 @div,它们会一起缩短时值,减时线也会连接成一组:
@div({1 2 3 4}, 1) 等价于 {1 2 3 4}/这段代码给四个音符各加一条减时线,并用一条连续的线把它们连接起来,而不管节奏如何切分、是否自动分组——即强制分组。基于此我们可以手动调整减时线的连接:
@set(div.autobeam=false) % 这行不写也没事,因为下面强制先连接2和3
1/ {2 3}/ 4/使用 @beam 手工连接
Section titled “使用 @beam 手工连接”我们还可以使用 @beam 明确指定一组减时音符。它接收一串标签,按参数顺序连接对应元素已有的减时线:
0/ 1/. 2// 3/
@set(div.autobeam=false)
0/ 1/.@a 2//@b 3/@c @beam(a, b, c)这里先关闭自动连接,再给三个连续音符标上 a、b、c,最后由 @beam(a, b, c) 把它们连成一组。@beam 不受 div.autobeam 设置影响,也不会替音符添加新的减时线;音符本身仍需通过 / 或 @div 具有相应的减时线。
端点必须按时间顺序排列,并且是同一音轨、同一谱面行中的相邻可见元素。中间夹着未传给 @beam 的音符、跨越换行或连接不同音轨都会报错。不传标签时,@beam() 会尝试使用它前面最近的两个可标注对象;明确写出标签通常更容易读懂,也更适合连接三个以上的音符。
@div缩短时值并绘制减时线,@dot添加附点,@dash创建增时线。/、.、-是三个函数的日常简写,可以组合成1/.、1//、1 --等节奏。@meter设置拍号、检查小节时长并决定减时线的自动连梁分拍单位,但不改变音符自身时值,也不自动插入小节线。@bar创建小节线;|分隔小节,||是双竖线,|||表示终止,|:与:|标出反复段,小节线本身不占时值。@tie连接音符,同轨同音且时间连续时合并延音;height只控制连音线的弧高,默认0自动调整,正数为固定高度。@tuplet({content}, normal)多连音,按最短时值单位缩放整组节奏,自动推导并显示连音数,同时改变实际播放时长。- 同一个
@div({...})中的减时线始终连接;独立的div默认按当前拍号的分拍单位自动分组。 autobeam=false关闭不同div之间的自动连接,@beam则用标签手工指定连接关系。
完整参数和默认值可以随时在函数速查中查看。