SC:字符串,字符串集合

文章目录[隐藏]

一个字符串被以一个数组的形式储存。数组最后一个项目是0。0,或终止,代表了字符串的结束。字符串可以是任何用引号包围的字符组合(字词或数字),比如”my 4 strings”。SC内部,将数组中每个字符以ascii整数形式存储。第一位是’m’ (176),第二位’y’ (121),第三位’ ‘ (空格或 32),第四位也是一个字符,不是数字,’4’ (111)。因为是数组的关系,它可以被含入do函数内。

23.1. 作为数组的字符串

"CharacterArray".at(0) // 尝试将索引数在 0 至 13 间改变

"CharacterArray".at(0).ascii

"This is a string that is actually an array".do(
   {arg each, count;
      [count, each.ascii, each].postln;
   })

一个字符串数组是数组的数组或多维数组。数组[“one”, “two” “three”]由三个数组构成。第一个数组包含字符’o’, ‘n’, ‘e’, 和0。第二个数组是’t’, ‘w’, ‘o’, 和0。

数组懂数学。字符串,即使数组懂数学,但也不是你想象的那种。如果你想对一组音移调,你可能会尝试向字符串或字符串数组加一个数字(比如,”C#” + 5),如下例:

23.2. “C” + 5?

("C#" + 5)

(
a = ["C#", "D", "Eb", "F", "G"];
a = a + 5;
a.postln;
)

这个例子能跑,但结果不是你想要的。如果我们需要程序生成数字,但列印字符串,该怎么做呢?可以通过将字符串数组用作参照(reference)来实现。

这是一个字符串数组,其中一行代码列印一个跟随一个随机选择的字符串之一,以及一个随机选择的do:

23.3. pitch array index

(
a = ["C", "D", "E", "F", "G"];
a.at(3).postln; //post item at index position 3 in the array a
)

(
a = ["C", "D", "E", "F", "G"];
a.at(5.rand).postln;
)

(
a = ["C", "D", "E", "F", "G", "A", "B"]; //pitch class array
"count\trandom\tpitch at index:".postln; //header
10.do( //do 10 items
   {arg item, count; //use arguments item and count
      var pick;
      pick = a.size.rand;
      count.post; "\t\t".post; //print the number of this iteration
      pick.post; "\t\t".post; //print the number I picked
      a.at(pick).postln; //print the item at that array position
   })
)

你可以用连结消息++保存postln消息。这用于同时输出两个字符串。因此”this ” ++ “string” 将变为 “this string”。另一个联合数据的方式是列印整个包含一组项目的数组,例如[count, b, a.at(b)].postln;。最后,你可以使用postf,它通过向一个字符串插入一串引数替代”%”字符来格式化一条列印消息。反复运行下例以确定它的确在选取不同的值。第二例是更简明版本。

23.4. 被连结的字符串

(
a = ["C", "D", "E", "F", "G", "A", "B"];
10.do(
   {arg item, count; var b;
      b = a.size.rand;
      ("Item " ++ count ++ " : " ++ b ++ " = " ++ a.at(b)).postln;
      // 或
      // postf("Item % : % = %\n", count, b, a.at(b))
   })
)

更简洁

do(10, { ["C", "D", "E", "F", "G", "A", "B"].wrapAt(100.rand).postln;})

现在我便能用12音旋律结合字符串数组了。

23.5. Every 12-tone row with pitch class strings

(
//初始化 MIDI, 先运行它
var original, total, begin, next, art, pcstrings, count;
original = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
pcstrings = ["C ", "C# ", "D ", "Eb ",
   "E ", "F ", "F# ", "G ", "Ab ", "A ", "Bb ", "B "];
total = 479001600;
count = 0;
begin = total.rand;
next = 0.125;
art = 0.6;
("Total playback time = " ++ (total*next/3600).asString ++ " hours.").postln;
r = Task({
   inf.do({
      var thisVar;
      thisVar = original.permute(begin + count);
      thisVar.do({arg e; pcstrings.at(e).post});
      "".postln;
      (thisVar + 60).do({arg note;
         m.noteOn(1, note, 100);
         thisThread.clock.sched(next*art, {m.noteOff(1, note, 100); nil});
         next.wait
      });
      count = count + 1;
   })
})
)

//然后这些
r.start;
r.stop; 127.do({arg i; m.noteOff(1, i, 0)})

观点一刻

对我来说,计算机辅助创作的目标是机器为我做一切繁琐细节的部分,然后我继续干那些创造性的有趣的部分。下例的结果仅列印音高,而不是音乐。即使如此,我们可以停在这,并且它将在创作练习中很有帮助。这接近于40年前如何做这个事。创作者开始于你现在可以做的事:至少让计算机去处理数字。但占用了四页的代码或上百张穿孔卡片(punch card)。对SC来说,这只用一行。刚好有这样一个例子(第一个值在八分之一内循环,第二个是下一个距八分之一的时间,下一个是MIDI音,下一个是音量):

23.6. 伊利亚克组曲(Illiac suite)?

60.do({[8.rand, 8.rand, (rrand(36, 72)), 10.rand].postln;})

这比希勒(Hiller)50年代的程序先进一大截。但我仍无法将这些东西抄作手稿,然后让其他人演奏它。当今科技的好处是快速的回放。即使我最后的成品是打算为真正的音乐家所用,我仍可以用计算机先做尝试。我可以对比一分钟四次和数月四次的区别。

十年前,我们让CPU能够产生实际的声音,但却要花掉一整夜的时间。在2000年,那段时间被削减到5分钟,但却仍要用上几页代码和两个程序(一个压碎(crunch)数字,另一个生成声音)。今天,声音是实时生成的,而且仅需大约十行代码。

练习,随机学习

这有一个范例。基于几个简单点子的完整创作:三个乐器,一套事件数字,随机选择音高、持续时间、下一事件以及振幅。设置你的MIDI回放,这样通道1,2,3才能有三个不同的乐器。

我需要补充,这个实验并不那么有趣。但我们的目标是快速实验转向。所以听一会儿这个例子,然后操一下那些随机选项再听一会儿。改变持续时间、下一事件、音高选择等等的范围。在随机范围外(比如 duration = rrand(0.5, 2.0)),试试为选择数组设定一个随机索引(比如 duration = durationArray.at(10.rand))。在一个音高数组内尝试不同的scale。用频率替代MIDI值。相比一个无限的do,建立一系列为正式设计定义的do循环,改变每个的参数(20个长循环然后5个短循环,高音然后低音,等等)。

23.7. (倾向性) 随机学习

( 
a = Task({ 
   inf.do({arg i; 
   var note, dur, next, amp, inst; 
   note = rrand(24, 84); 
   dur = rrand(0.1, 0.5); 
   amp = rrand(30, 127); 
   next = rrand(0.1, 0.5); 
   m.noteOn(1, note, amp); 
   thisThread.clock.sched(dur, {m.noteOff(1, note); nil}); 
   next.wait 
   }) 
}); 

b = Task({ 
   inf.do({arg i; 
   var note, dur, next, amp, inst; 
   note = rrand(24, 84); 
   dur = rrand(0.1, 0.5); 
   amp = rrand(30, 127); 
   next = rrand(0.1, 0.5); 
   m.noteOn(2, note, amp); 
   thisThread.clock.sched(dur, {m.noteOff(2, note); nil}); 
   next.wait 
   }) 
}); 

c = Task({ 
   inf.do({arg i; 
   var note, dur, next, amp, inst; 
   note = rrand(24, 84); 
   dur = rrand(0.1, 0.5); 
   amp = rrand(30, 127); 
   next = rrand(0.1, 0.5); 
   m.noteOn(3, note, amp); 
   thisThread.clock.sched(dur, {m.noteOff(3, note); nil}); 
   next.wait 
   }) 
}); 
) 

a.start; 
b.start; 
c.start; 
a.stop; 127.do({arg i; m.noteOff(1, i)}) 
b.stop; 127.do({arg i; m.noteOff(2, i)}) 
c.stop; 127.do({arg i; m.noteOff(3, i)})
Be Sociable, Share!

Published by

ww1way

http://about.me/ww1way

Leave a Reply

Your email address will not be published. Required fields are marked *