SuperCollider有很多收集(collection)类,但对于一些简单的任务来说,你往往可以通过在方括号内定义数据的数组(Array)来实现:
a= [5,6,7,8,9,10];
有时我们需要更清晰的建构数据列,并且我们可以书写我们自己的函数来生成数据:
a= Array.fill(6, {arg i; i+5});
你将会在今后渐渐熟悉收集类比如数组的用法,但现在我将首先展示一些小窍门给你尝尝鲜(逐行运行一下逐行,在post窗口内观察结果)。
创建数组不同的方式:
// 序列的引数是元素的数量,起始元素和递增值 Array.series(10,1,1) (1..10) // 做同样事情的捷径
Array.series(10,1,2) (1,3..20) // 同样的,一个捷径
// 几何而不是算术序列:引数是元素的数量,起始元素以及增长率(ratio) Array.geom(10, 1, 1.1); // 注意,复合定律将使这些数字快速扩张! Array.geom(10, 1, 10); // 随机产生在0.7到2.4间线性分布的10个随机值 Array.rand(10, 0.7,2.4);
另外一些操控数组的方式:尝试顺序运行以下诸行,然后注意post窗口内返回的内容!
a = [1,3,5,6]; a+5 a*8 a**2 //take to power of 2 a.squared //same thing a.sqrt a.scramble //run me multiple times! a.rotate(1) a.rotate(-1) a-10 (a-10).abs a>4 a.reverse
需要集中精力,否则立马就在post窗口内lost了。。。如果你的post窗口会像我这里一样的用着用着傻逼掉(据说是Mac中文系统所导致,待考),你可以cmd+K重新编译它。
在数组中索引元素
b=[2,3,4,7] b.at(3) // 获取序列为3的元素 (意味着第四个元素) b.at(4) // 将不会返回任何东西,因为数组不够大! nil是“无可用返回值”的占位符,它的突然出现往往会带来麻烦 b.put(2,50) // 将50放到索引为2的口 (替代第三个元素) b // 注意b本身也已被改变 b.put(14,90) // 崩溃, 没地方摆这个90, 数组仅有4个元素口
你同样可以使用Java数组标记法
b[0] // 获取第一个元素 b[0]= 74 // 设置第一个元素 b // 也被改变了
有更多我们以后可能会碰到的集合类。迫不及待的你可以先读读他们的帮助文档:注意在操作中会有类的层级存在,因此一个方法将没有必要必须处于数组类中。
[Collections]
[SequenceableCollection]
[ArrayedCollection]
[Array]
关于效能的一点笔记
你将偶尔看到
// 创建一个固定的(非动态的)数组并稍稍实惠(cheaper)一些 // 尤其是当你在创建其后便不打算再改变它的时候 #[1,2,3]
而不是
[1,2,3] // 一个动态数组
它们的区别:
a= #[1,2,3]; a[0] // 可行 a[0] = 8 // 不可行,因为它无法被更改
更多关于混合(Mix)和数组
现在让我们来看看使用数组来帮助我们创建一个UGen网络——在这样的情况下,使用我们已经看过的自动通道扩张法非常简单,但你会发现这在更复杂的事件中也同样有用,比如说要你一次性混合一百个变化着的声音!
( // 如果你仅有一对立体声输出,你将仅能听到四个频率中的前两个 { var freqs,array; freqs= [440,443,447,455.7]; array=Array.fill(4, // 4个元素将进入到这个数组 {arg i; // 这个函数是创建每个元素的秘诀 SinOsc.ar(freqs.at(i), 0, 0.1) }); array }.scope )
// 我们可以使用Mix使其变为一个通道 ( { var freqs,array; freqs= [440,443,447,455.7]; array=Array.fill(4, // 4个元素将进入到这个数组 {arg i; // 这个函数是创建每个元素的秘诀 SinOsc.ar(freqs.at(i), 0, 0.1) }); Mix(array) }.scope )
// 这是一个使用Mix.fill的捷径 ( { var freqs; freqs= [440,443,447,455.7]; Mix.fill(4, // 4个元素将进入到这个数组 {arg i; // 这个函数是创建每个元素的秘诀 SinOsc.ar(freqs.at(i), 0, 0.1) }); }.scope )