一、初识gm
首先通过一个简单的例子来初步认识一下gm包。
这里有一段很简单的代码,它是用这个包写的。这段代码可以生成一段乐谱还有相应的音频。这段代码也可以直接在RMarkdown中工作,并且自动将生成的乐谱和音频嵌在生成的网页之中,音频可以直接播放。
这段代码非常简单,首先是加载R包,然后创造一个对象,最后将这个对象转化成音乐,我们现在来逐行看一下。
首先是Music这个命令,它会初始化一个Music对象,就像一个基底,可以往上加东西。
下一行是Meter这个命令,它相当于是设定这段音乐的拍号,也就是四四拍。
再往下这个命令Line,相当于添加了一条旋律线或者一个声部,这个声部包含了四个音符。
最后的show命令它就可以将这段音乐转化成乐谱和音频。
library
(gm)


m <-

Music() +

Meter(
4
,
4
) +

Line(list(
"C5"
,
"D5"
,
"E5"
,
"F5"
), list(
1
,
1
,
1
,
1
))


show(m, to = c(
"score"
,
"audio"
))

这是一个非常简单的例子,但它展示了gm的核心特征。如果要用一句话来概括gm它到底是什么,可以这么说:gm就是一套用来生成音乐的语言。
具体来说的话,gm有下面这些特点。

、gm的特点

1. 语法直观

gm的语法,非常简单直观。如果你熟悉著名的作图包ggplot的话,你会发现gm的语言和它非常相似,可以通过加法的操作不断添加新的成分。
比如我们回到前面最开始的这个例子。我们可以继续往上添加东西,用类似于ggplot的语法,比如可以设定拍速,在代码中加上一个Tempo的命令。
m <-

Music() +

Meter(
4
,
4
) +

Line(list(
"C5"
,
"D5"
,
"E5"
,
"F5"
), list(
1
,
1
,
1
,
1
)) +

Tempo(
120
)
# 设定拍数

show(m, to = c(
"score"
,
"audio"
)
也可以继续添加新的声部。大家注意乐谱的前后变化,现在多了一条声部,声部依然可以播放。
m <-

Music() +

Meter(
4
,
4
) +

Line(list(
"C5"
,
"D5"
,
"E5"
,
"F5"
), list(
1
,
1
,
1
,
1
)) +

Tempo(
120
) +

Line(list(
"C4"
,
"G4"
), list(
2
,
2
))
# 添加新的声部

show(m, to = c(
"score"
,
"audio"
))

还可以继续添加调号。比如现在在谱子上添加了一个降E大调的调号,大家可以对比前后的谱。

m <-

Music() +

Meter(
4
,
4
) +

Line(list(
"C5"
,
"D5"
,
"E5"
,
"F5"
), list(
1
,
1
,
1
,
1
)) +

Tempo(
120
) +

Line(list(
"C4"
,
"G4"
), list(
2
,
2
)) +

Key(-
3
)
# 添加调号

show(m, to = c(
"score"
,
"audio"
))

关于添加的更多功能可以查看gm的文档。

2. 可编程

我们可以用gm来进行一些音乐编程的操作。还是来看一个例子。这段代码中有两个变量:第一个变量pitches,它相当于定义了四个音高;第二个变量durations,它定义了四个时长。这两个变量结合起来,就相当于定义了四个音符,这四个音符有相应的音高和相应的时长。我们可以用gm这个包把它转化成乐谱。
pitches <- c(
60
,
62
,
64
,
65
)

durations <- c(
1
,
1
,
1
,
1
)


m <- Music() + Meter(
4
,
4
) +

Line(as.list(pitches),as.list(durations))


show(m)

现在看到就是do re mi fa这四个音。
如果想让它的音高整体移高一个五度,只需在pitches这个变量后面加上7即可。
pitches <- c(
60
,
62
,
64
,
65
) +
7# 移调
durations <- c(
1
,
1
,
1
,
1
)


m <- Music() + Meter(
4
,
4
) +

Line(as.list(pitches),as.list(durations))


show(m)
这样就得到了一组新的音高。这时我们给它转化成乐谱,就可以发现这段乐谱谱子上面这四个音符比之前高了一个五度,而在这个过程中唯一的操作就是在变量pitches上加了7,这就是所谓的音乐编程。
我们还可以对时长进行操作。比如在durations这个变量后面乘2,这就相当于把每个音符时间都扩大了一倍。
pitches <- c(
60
,
62
,
64
,
65
)

durations <- c(
1
,
1
,
1
,
1
) *
2# 延长

m <- Music() + Meter(
4
,
4
) +

Line(as.list(pitches),as.list(durations))


show(m)
可以发现谱中这四个音已经延长了一倍的时间。
这两个例子就是展示了所谓的音乐编程。我在开发gm的时候,有意的使用R原生的一些数据结构来表征音乐,这样的话大家很容易就可以将R语言的编程技巧直接使用到音乐编程之中。

3. 可在RMarkdown和R Jupyter Notebook中使用

gm是可以直接在RMarkdown中使用的,除了R markdown之外,还可以在Jupiter notebook里面使用,也就是python notebook。你也可以直接在RStudio里面或者是一般的Rconsole中使用,它会生成生成网页或者生成PDF文档或者word文档,而生成的乐谱可以直接嵌入在生成的这些文档当中。比如在RMarkdown中可以设定生成的文档类型,gm会自动按照设定生成乐谱然后自动嵌入到这些文档之中。

三、gm的用途

1. 在各种场合嵌入音乐

比如之前,有一个音乐学的教授和我提过,他准备在给学生的课件中使用这个包,就不用手动去加载这个乐谱,可以自动生成,会非常方便。还有在Twitter上有朋友给我留言说,可以在你做报告的时候,在你的报告里面突然来一段音乐。总之你可以就是用各种思路在各种文档中加入音乐。

2. 算法作曲

我最开始写这个包的时候,也是因为我当时在写一个自动作曲的程序,或者你也可以称之为算法作曲。我当时想要有一个更好用、更顺手的一个工具,于是就开发了gm这个包。
算法作曲什么意思?简单的说,就是用算法来生成音乐,而不是说直接去写音乐。我们还是来看一个例子。在下面这个例子中,我们可以看到这个谱上有9个声部。这9个声部的内容,它的音符都是一样的,音符的节奏也一样,唯一的区别是每一条声部的入场时间会比前一条慢一点点,这样的话,一起播放的时候会形成一种很有趣的回响的效果。
pitches <- as.list(c(
64
,
65
,
69
,
71
,
72
,
76
))

durations <- rep(list(
1
),length(pitches))


m <- Music() + Meter(
4
,
4
)


for
(i
in0
:
8
) {

m <- m + Line(pitches, durations, offset =
0.5
* i)

}


show(m, to = c(
"score"
,
"audio"
))

生成这段音乐的核心代码其实是就是这个这段for语句。这一段代码中间有一个off set这个参数,它相当于是决定了每条声部入场的时间,每一条声部都比前一条声部慢一点,最后导致了这个效果。在这个例子中,我们是靠算法来生成所有的音乐的,不需要手动去加载这些音乐,不需要手动去写,而是靠算法来生成这个音乐。大家回头也可以想想看,有没有更酷的例子,或者试试看去查阅一些算法作曲的书。
本文由志愿者徐雪茵根据作者毛任飞在第14届中国R会上的演讲记录整理形成。

作者介绍:

毛任飞,基于科学的课程设计师 (science-based course designer) 和教师,有七年的教育经验,学生从学龄前至初中。课程主题包括创造力和非智力因素(non-cognitive factors)。独立 R 语言开发,作品有 R 包 gm,用来生成乐谱和音频。独立音乐人,作品专辑《夜》正 在开发中,见https://flujoo.github.io/en/my-music-album-night/。擅长自学,所有工作和兴趣所需要的知识和技能均靠自学获得。

编辑:张露

---END---
统计之都:专业、人本、正直的中国统计学社区。

关注方式:扫描下图二维码。或查找公众号,搜索 统计之都 或 CapStat 即可。
往期推送:进入统计之都会话窗口,点击右上角小人图标,查看历史消息即可。
继续阅读
阅读原文