在这一节,我们将谈谈不同类型的随机进程。并不会有很多人去写纯的随机音乐(尽管看起来像是)。总之这不是非常有趣的。通常会有一些过滤、倾斜(skew)或倾向(bias)。即使看起来选择的面很宽,所有可被听到的频率(30Hz~20000Hz),对于那些频率都有一个倾向。在之前的“随机”音乐范例中,我们倾向于一个MIDI值的范围(而不是连续的频率),可能的持续时间的范围,等等。即使凯奇(John Cage)的作品常被认为是随机的,但他们仍由倾向塑造。4’33″便具有一个强烈的倾向:没有来自于钢琴的音符。
随机是什么?一致是什么?设想一个从完全一致走向彻底随机的音阶。两者最后会是什么?在数字音频方面,一个声音由一个16比特的数字表述,彻底随机意味着一个在一个新采样生成同时在16比特范围内数字选取的平等机会。这样的一个系统将生成噪音。彻底的一致我猜将会全部是0。
我喜欢去思考随机的程度。韦伯听上去比莫扎特更随机。我的意思是韦伯的模式更难辨识。我们在音乐体验中寻找的,是相似点与多样化间那个舒适的平衡点。这随人、心情或环境(比如,音乐厅VS影院(在这里似乎更有耐受力))的不同而不同。有两种接近这个平衡点的方式。一是增加复杂的程度(像在加法合成中做的那样),另一个是过滤复杂的程序(像在减法合成中那样)。在本章中,我们将做过滤。
倾向性随机选取
倾向性随机选取限制或滤除了一系列宽泛可能出现的结果。我们见过它多次,比如随机范围:rrand(60,72)。另一个方法是加重(weight)一个值或一组值出现的可能性。在这些系统中,每个可能性的比重被表述为0~1之间的值,在这里所有可能性最多加到1。在上边那个随机的例子中,任何在60~71之间的值都有平等的可能性被选中,因此每个独立值有1/12或0.08333的机会被选中。

同样的,在[60, 65, 69, 54].choose中,每个值都有0.25的机会被选中。因为只存在四个值(0.25*4=1.0)。
一个想向单一值倾斜的方式是重复选择:
24.1. 老千骰子
[60, 60, 65, 69, 54].choose
(至于为什么上例60出现的机会会比较高就不用说了吧。)
在10.0.rand的情况下,选择并非离散的整数,但却是可能的浮点值。展示这些机率的图表应是横跨顶部的一条直线,表明每个低值(0.0)到高值(10.0)间的数组都有被平均选取的机会。

对这个模型做有倾向的输出需要一点数学知识。
关于随机倾向,这里是一个很好的例子。三个人为得到最大的数字转一个转盘。如果你转到小的数字那么就继续转。结果倾向于较大的数字,因为数字最大代表获胜。
将这个过程用一对骰子展示:两颗骰子一起摇,但取两个数字里最大的那个。可能的组合方式有:
[ 1, 1 ] [ 1, 2 ] [ 1, 3 ] [ 1, 4 ] [ 1, 5 ] [ 1, 6 ]
[ 2, 1 ] [ 2, 2 ] [ 2, 3 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ]
[ 3, 1 ] [ 3, 2 ] [ 3, 3 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ]
[ 4, 1 ] [ 4, 2 ] [ 4, 3 ] [ 4, 4 ] [ 4, 5 ] [ 4, 6 ]
[ 5, 1 ] [ 5, 2 ] [ 5, 3 ] [ 5, 4 ] [ 5, 5 ] [ 5, 6 ]
[ 6, 1 ] [ 6, 2 ] [ 6, 3 ] [ 6, 4 ] [ 6, 5 ] [ 6, 6 ]
本例可以用这行代码生成:6.do({arg i;6.do({arg j; [i + 1, j + 1].post}); “”.postln;})
每对含6的组合将返回6。但仅有一对会返回1:[1, 1],依此类推。

有11种组合的结果是6(11/36=0.3),9种组合的结果是5(0.25),7种4(0.19),3种2(0.08),然后仅1种1(0.03)。下边是这些值的可能性分布图表。

用100面的骰子将给出更多的数字,但趋势将是完全相同的。100和其他任何数将返回100。但仅有1和1的组合将返回1。每个数字返回结果总数可以用公式n*2-1计算。每个数字的可能性由(n*2-1)/total来计算。total是最大的那个值。
24.2. 高倾向计算
n = 100; n.do({arg i; i = i + 1; ((i*2-1)/(n.squared)).postln})
下边是一个基于“两者中较大值”倾向做的50个选择图表。选择越多,可能性图表曲线越平滑。

浮点数的随机选取有更多的可能性(尽管仍是有限的)。趋势图是一样的。
在SC中,你可以使用max和min函数。
24.3. 浮点倾向
max(6.0.rand.round(0.01), 6.0.rand.round(0.01));
任何数字和6将返回6,但只有0和0返回0。这个功能的图表将是:

这段代码的可能性图表将是怎样的?
24.4. 倾向
min(100.0.rand, 100.rand);
一个有点点难的问题:这段代码如何改变输出(注意第二个随机选择不是一个误写,我使用100.rand表明这是一个证书选择而不是浮点):
24.5. 倾向
max(200.0.rand, 100.0.rand);
这个怎么样(可能的结果是0~100,但问问你自己有多少组合的结果是0?多少种结果是50?多少种是100?):
24.6. 倾向
(100.rand + 100.rand)/2
如何做一个反向的三角?-10~0间的一个选择?一个对于-10的倾向?在0~10间倾向于7.5的选择?如何将一个选取机率分配给每个值,使得60有0.25的机率被选上,61有0.1的机率,62有0.5,等等?
复杂吗?过去曾经是。SC有一堆很好的随机选取数字倾向函数。在我们着眼它们前,我要示范一个做测试的系统。我惯常使用的方法是申明一个能保持记录随机选取的计数数组,然后依选择的出现增加数组的位置。最后,我使用plot信息,它将绘制这个数组的平面图。运行下边第一行看结果。
24.7. 测试倾向
[0, 1, 0.5, 0.178, 0.9, 0].plot; // plot一个数组 ( a = Array.fill(100, {0}); //用0填充一个数组 1000.do( //做1000次反复; 更多选择, 更平滑的图表 { b = 1000.rand; //从0~999间选取一个随机数 a.put(b, a.at(b) + 1); //在数组中增加那个位置 } ); a.plot; //平面画结果. )
随机的选择在0~999间。这个数字被用做一个参考的索引并使用put增加数组a的位置。put的第一引数为数组的索引,第二个是你要储存的值。它在索引b处改变值(通过增大1(a.at(b)+1))。用这个方法便可以测试我们上边讨论的每个随机进程,或列在下边的函数。
在上边的例子中使用某些倾向随机选取会返回浮点数。这时,在将它用于数组索引前,你必须将它转化为整数。
24.8. 测试浮点倾向
( a = Array.fill(100, {0}); //用0填充数组 1000.do( //做1000次反复 { b = (100.rand + 100.rand)/2.div(1); a.put(b, a.at(b) + 1); } ); a.plot; //plot结果. )
随机函数及测试。
24.9. 随机测试
( a = Array.fill(100, {0}); 1000.do({ b = 100.rand; // 0 和这个, rand2 生成负值 (负的这个到这个) a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ b = 100.linrand; // 线性分布, bilinrand adds - values a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ b = rrand(30, 75); // random range a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ b = 100.exprand(1).div(1); a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ b = max(100.rand, 100.rand) a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ b = max(100.rand, 100.rand, 100.rand); a.put(b, a.at(b) + 1); }); a.plot; ) ( a = Array.fill(100, {0}); 1000.do({ //this.coin returns true this percent of the time b = if(0.2.coin, {max(20.rand, 20.rand)}, {min(80.rand, 80.rand) + 20}); a.put(b, a.at(b) + 1); }); a.plot; )