一、初识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"))

au1

这是一个非常简单的例子,但它展示了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"))

au2

也可以继续添加新的声部。大家注意乐谱的前后变化,现在多了一条声部,声部依然可以播放。

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"))

au3

还可以继续添加调号。比如现在在谱子上添加了一个降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"))

au4

关于添加的更多功能可以查看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)

au5

现在看到就是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)

au6

这样就得到了一组新的音高。这时我们给它转化成乐谱,就可以发现这段乐谱谱子上面这四个音符比之前高了一个五度,而在这个过程中唯一的操作就是在变量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)

au7

可以发现谱中这四个音已经延长了一倍的时间。

这两个例子就是展示了所谓的音乐编程。我在开发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 in 0:8) {
  m <- m + Line(pitches, durations, offset = 0.5 * i)
}

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

au8

生成这段音乐的核心代码其实是就是这个这段for语句。这一段代码中间有一个off set这个参数,它相当于是决定了每条声部入场的时间,每一条声部都比前一条声部慢一点,最后导致了这个效果。在这个例子中,我们是靠算法来生成所有的音乐的,不需要手动去加载这些音乐,不需要手动去写,而是靠算法来生成这个音乐。大家回头也可以想想看,有没有更酷的例子,或者试试看去查阅一些算法作曲的书。

本文由志愿者徐雪茵根据作者毛任飞在第14届中国R会上的演讲记录整理形成。

作者介绍:

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

发表/查看评论