用spread()编辑节奏
初见Spread()
在上一节,我们编写了一段简单的精简代码。而同一pattern,在sonic pi中有更精简的写法,就会用到本章即将介绍的spread()函数。
use_bpm 120
live_loop :drums do
tick
sample :drum_bass_hard if (spread 4,16).look
sample :drum_snare_hard if (spread 2,16).rotate(4).look
sample :drum_cymbal_hard if (spread 8,16).look
sleep 0.25
end
中间三行分别在播放底鼓,军鼓,镲的采样。仔细观察,你会发每个乐器都用到了spread函数。对照谱子来看,你肯定能猜出spread的作用。
Kick X - - - X - - - X - - - X - - -
Snare - - - - X - - - - - - - X - - -
Hihat X - X - X - X - X - X - X - X -
底鼓在一小节的16步中敲击4次,所以是 (spread 4,16)。
军鼓在16步中触发2次,即是 (spread 2,16)。
镲片同理。
这么看来,告诉spread你想在一小节里打几次鼓,他就会老实照办。不过我们为了严谨一些,还是看看官方文档对spread用法的解释吧。
Spread()函数的用法
从文档看,spread()函数首先会按照指定长度创建一组boolean数列,数列只有true/false两种状态。类似于音序器每一步开关的状态。而开启的步数是由你来指定的,程序会自动让开启的灯保持数学意义上的均匀排列。
Spread(开启步数,数列长度)
根据我们的实例,数列长度是16。不过在实际使用中,长度也可以自定义。
数量长度的设置
一小节16步并不是铁律,当然你也可以设置成一小节32步。在写短促的closed-hihat的时候,我常会用到一小节32步的设置。但只是把spread(x,16)改成spread(x,32),容易出现问题。
因为改变一小节内的步数,也需要关联到后面sleep的时值。
所以正确的配置是:
16步
spread(x,16) ---- sleep 0.25
32步
Spread(x,32) ---- sleep 0.125
使用真正的音序器修改很方便,轮到自己写程序时就需要算算术了。我之前因为没有修改sleep数值,使声音变得奇怪,不过听起来不错的错误也可以保留下来。
Spread平均大法
之前举例的情况其实不算特殊,因为16步可以被均匀分成2份,4份,8份,这都是能被整除的情况。如果将16步均分成5份,似乎就不那么平均了。但是spread(5,16)并没有报错,证明它还是努力把16步分成5份。
这个算法借助了物理中中子源加速器的算法:
参见论文《The Euclidean Algorithm Generates Traditional Musical Rhythms》
这个方法能均分任何不能被整除的数列。虽然从视觉上看并不是均分,但是科学家会用数学方法,证明它的结果接近均分。从图像上看,均分的结果确实四平八稳, 如果您有兴趣可以阅读这篇论文。
spread(5,16)所做的事大概是这样:
Step 1
[1 1 1 1 1 00000000]
Step 2
[1 0][1 0][1 0][1 0][1 0] [0] [0] [0]
Step 3
[1 0 0] [1 0 0][1 0 0][1 0][1 0]
Step 4
[10010][10010][100]
Step 5
1001010010100
直观来看,这个过程就是把后面的0匀到前面的过程。虽然不能断定在节奏中,搞平均主义就是好。但在很多世界音乐的节奏型中。找到和spread结果相近的现象。所以在你写节奏没有任何灵感的时候,可以尝试使用spread。
使用Spread()编写复合节奏
live_loop :euclid_beat do
sample :elec_bong, amp: 1.5 if (spread 3,8).tick
sample :perc_snap, amp: 0.8 if (spread 7,11).look
sample :bd_haus, amp: 2 if (spread 1,4).look
sleep 0.125
end
在文档中给出了复合节奏的示例。简言之在复合节奏里,一段节奏不一定非要在标准的一小节内循环一次。也可以是11拍一循环,5拍一循环。它们与其他4,8拍一循环的节奏,共同形成复杂的变化。
不同乐器间。节奏的周期性同步与错位是一种很有趣的效果。我想在钢琴卷帘里手动写出复合节奏会是一件挺麻烦的事。这类复合节奏,应该是程序最擅长的效果之一吧。
旋转你的节奏
rotate是spread函数可选的一个参数,并不是必须要设置的。在你确定节奏时,可以使用rotate进行微调。在程序中表示节奏,采样的触发与否分别被true/false所代替。Rotate 以true与后面一个或多个false为单位,旋转整个节奏。
至于你的旋律究竟是如何旋转的,我们还是把结果打印出来吧:
puts (spread 3,8)
#=> (ring ture,false,false, true,false,false, true,false)
puts (spread 3,8,rotate: 1)
#=> (ring true,false,false, true,false, ture,false,false)
puts (spread 3,8,rotate: 2)
#=> (ring true,false, ture,false,false, true,false,false)
puts (spread 3,8,rotate: 3)
#=> (ring ture,false,false, true,false,false, true,false)
到rotate:3 的时候,节奏又变回了刚开始的模式。
不过在实际编写中,不需要像这样查看真正输出的节奏型,而是依赖自己的耳朵与直觉。rotate数值在这个时候会变成你寻找最理想节奏的符号。所以在运行过程中请大胆修改数值吧!
将多个打击乐器并入同一轨道
将全部乐器并入同一轨道,就要同步所有乐器的节拍。这就涉及spread()后面.look的用法。但是说到.look,我就一定要讲.tick,因为我之前经常把它俩搞混,导致运行时出错。
这里给出一些我认为安全的写法。
look与tick在运行效果上其实没有特别大的差异,它们都是在遍历spread()输出的boolean数列。也就是说tick与look在每一次循环中读取你乐谱中的每一步,速度是按照你规定时值来的。
但是将两种方法写进同一个live_loop里就是灾难,所以搞清他们各自的写法很重要。
.look的写法
use_bpm 120
live_loop :drums do
tick
sample :elec_bong, amp: 1.5 if (spread 4,16).look
sample :perc_snap, amp: 0.8 if (spread 2,16).look
sample :bd_haus, amp: 2 if (spread 8,16).look
sleep 0.25
end
这是上面实例的代码,三种乐器都用到.look。只要记得在这个轨道内开头加入tick就好,这是让三种乐器同步的打点器。
.tick的写法
tick与look区别在于tick自带一个打点器。如果你在同一live_loop内使用多个tick,那么共用打点器的情况会导致你设置的节奏不起作用。
所以解决办法是告诉计算机为不同乐器创建自己的打点器。具体方式是像这样命名.tick(:kick)。将上述代码用tick表示就是这样:
use_bpm 120
live_loop :drums do
tick
sample :elec_bong, amp: 1.5 if (spread 4,16).tick(:kick)
sample :perc_snap, amp: 0.8 if (spread 2,16).rotate(4).tick(:snare)
sample :bd_haus, amp: 2 if (spread 8,16).tick(:hihat)
sleep 0.25
end
附:曲风与节奏
这里列出spread可以做出的世界音乐节奏。
原文出自论文《The Euclidean Algorithm Generates Traditional Musical Rhythms》与sonic pi 官方文档。
#13世纪波斯节奏 Khafif-e-ramal
Spread(2,5)
#拉美哥伦比亚的经典节奏型
特立尼达卡里索普民歌
Spread(3,4)
#既是13世纪波斯节奏,也是罗马尼亚民间舞蹈节奏
Spread(3,5)
#保加利亚民间舞蹈节奏
Spread(3,7)
#古巴三连音节奏
Spread(3,8)
#保加利亚民间舞蹈节奏
Spread(4,7)
#土耳其Aksak节奏
Spread(4,9)
# Frank Zappa 在Outside Now中用到的节奏
Spread(4,11)
#常见的阿拉伯节奏 York_Samai
Spread(5,6)
#常见的阿拉伯节奏 Nawakhat
Spread(5,7)
#古巴五拍一节的cinquillo节奏
Spread(5,8)
#常见阿拉伯节奏 Agsag-Samai
Spread(5,9)
# 穆索尔斯基<图画展览会>用到的节奏
Spread(5,11)
#南非儿童歌曲的击掌节奏
Spread(5,12)
#巴西bossa nova节奏
Spread(5,16)
#典型手鼓节奏
Spread(7,8)
#常见西非bell节奏
Spread(7,12)
#巴西桑巴节奏
Spread(7,16)
#中非节奏
Spread(9,16)
#中非阿卡俾格米人的节奏
Spread(11,24)
#另一个阿卡俾格米人的节奏
Spread(13,24)