# SC：运算符，优先级，引数，表达式和用户自定义函数

### 运算符，优先级

19.1. 运算符 (+, /, -, *)

`1 + 4`
`5/4`
`8*9-5`
`9-5*8`
`9-(5*8)`

19.2. 更多运算符

`1 + 2 / 4 * 6`
`2 / 4 + 2 * 6`
`(2 * 6) - 5`
`2 * (6 - 5)`

`10 > 5`
`5 < 1`
`12 == (6*2)`
`106%30`

> 和 < 符号返回：真(true)和假(false)。SC知道10大于5（因此为真）以及5不比1小（假）。我们将把这一逻辑用于后边的章节。 模(%)是非常有用的运算符，它返回第一个数字处以第二个数字之后最小的余数。比如说，43%10 将返回3，12946%10 是6。一个普遍的音乐应用是模12，它将数字减至12一下，或一个八度。 你能预见这些表达式的结果吗？ 19.4. 预知

`(8+27)%6`
`((22 + 61) * 10 )%5`

### 消息，引数，接收器

19.5. 音乐相关的消息

```cos(34) //返回余弦

abs(-12) //返回绝对值

sqrt(3) //平方根

midicps(56) //给一个MIDI数字，在一个等音程内返回每秒周数

cpsmidi(345) //给每秒周数, 返回MIDI

midiratio(7) //给一个MIDI音程, 返回比率

ratiomidi(1.25) //给一个比率, 返回MIDI数字

rand(30) //返回一个0～29间的随机数

rand2(20) //返回一个-30～30间的随机数

rrand(20, 100) //返回一个20～100间的随机数

// 接收器表示法范例

30.cos //等于cos(30)

0.7.coin //等于coin(0.7)

20.rand //等于rand(20)

7.midiratio

// 二进制函数有两个引数

min(6, 5) //返回两个值的最小值

max(10, 100) //返回最大值

round(23.162, 0.1) //rounds first argument to second argument

// 引数可以是表达式

min(5*6, 35)

max(34 - 10, 4) //返回两个值的最大值```

### 练习，音乐计算器

SC甚至在你不做音乐的时候也很有用。我常只将它用作一个音乐计算器：计算平均律Ab的频率，平均律5度和自然音程5度间有几分，或者说音程，两个频率间的分数（cent）。下边是几个例子。

19.6. 音乐计算器

```// 大音阶频率
([0, 2, 4, 5, 7, 9, 11, 12] + 60).midicps.round(0.01)

// 大音阶音程率
[0, 2, 4, 5, 7, 9, 11, 12].midiratio.round(0.001)

// 佛里吉亚音阶频率
([0, 1, 3, 5, 7, 8, 10, 12] + 60).midicps.round(0.01)

// 佛里吉亚音阶音程率
[0, 1, 3, 5, 7, 8, 10, 12].midiratio.round(0.001)

// 平均和自然米索利地安音阶比较
[0, 2, 3, 4, 5, 7, 9, 10, 12].midiratio.round(0.001)

[1/1, 9/8, 6/5, 5/4, 4/3, 3/2, 8/5, 7/4, 2/1].round(0.001)

// 以平均律分表述的自然比率(米索利地安)Just ratios (mixolydian) in equal tempered cents
// (以及它们相较平均律的偏差)
[1/1, 9/8, 6/5, 5/4, 4/3, 3/2, 8/5, 7/4, 2/1].ratiomidi.round(0.01)

// 倒向12-音配置（Retrograde of a 12-tone set）
[0, 11, 10, 1, 9, 8, 2, 3, 7, 4, 6, 5].reverse

// 反向12-音配置 Inversion of a 12-tone set
12 - [0, 11, 10, 1, 9, 8, 2, 3, 7, 4, 6, 5]

// And of course, retrograde inversion (see where I'm heading?)
(12 - [0, 11, 10, 1, 9, 8, 2, 3, 7, 4, 6, 5]).reverse

// 12-音配置随机变调
([0, 11, 10, 1, 9, 8, 2, 3, 7, 4, 6, 5] + 12.rand)%12

// 12-音设置随机置换 (479,001,600之外)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].permute(479001600.rand) + 60```

### 函数，引数，范围

19.7. 函数

```(
var myFunc;

myFunc = {100 * 20};

myFunc.value.postln;
)```

19.8. 有引数的函数

```(
var func;
func = { arg a, b;
var r;
r = (b * 20)%a;
r.postln;
};
func.value(15, 5);
)```

19.9. 用数组引数的函数

```(
var func;
func = { arg a = 1, b = 2, c = 4;
[a, b, c].sum;
};
func.value(15, 5, 100);
)```
```(
var func;
func = { arg ... a;
a.postln;
a.sum.postln;
[a.sum, 1.0.rand.sum].sum
};
func.value(15, 5, 100);
func.value(15, 5, 100, 3, 78, 18, 367);
func.value(1, 2);
)```

```(
var func;
func = { arg a = 0, b = 0 ... c;
[a, b, c].postln;
c.sum.postln;
[c.sum, 3.0.rand.postln].sum.postln;
(a/b*c).postln;
};
func.value(15, 5, 100, 45);
func.value(15, 5, 100, 3, 99, 754, 78, 18, 367);
func.value(1, 2, 3, 4, 5);
)```

19.10. 有引数和变量的函数

```var func, outside = 60;
~myGlobal = 22;
func = { arg first = 5, second = 9;
var inside = 10;
inside = (first * 11)%second;
[first, second, inside, outside, ~myGlobal].postln; // 全部都行得通
(outside/inside).postln; //行得通
};
//inside.postln; // 反注释这一行，行不通
func.value(15, 6); // 引数被传递入函数```

19.11. 函数调用

```(//行1
var myFunc;
myFunc = { arg a = 10, b = 2;
b = (b * 100)%a;
b.postln;
};
myFunc.value; //行7
myFunc.value(15); //行8
myFunc.value(11, 30); //行9
)```

19.12. 关键字

```(
var myFunc;
myFunc = { arg firstValue = 10, secondValue = 2;
firstValue = (firstValue * 100)%secondValue;
firstValue.postln;
};
myFunc.value;
myFunc.value(firstValue: 15);
myFunc.value(firstValue: 30, secondValue: 11);
myFunc.value(secondValue: 30, firstValue: 11);
myFunc.value(secondValue: 23);
)```

19.13. 返回

```(
var octaveAndScale;
octaveAndScale = { arg oct = 4, scale = 0;
var scales, choice;
oct = (oct + 1)*12; //将"4" (C4)转换到MIDI八度(60)
scales = [
[0, 2, 4, 5, 7, 9, 11], //大调
[0, 2, 3, 5, 6, 8, 9, 11], //八音
[0, 2, 4, 6, 8, 10] //全音
];
scale = scales.at(scale); //more on the "at" message below
choice = scale.choose; //选一个音高
choice = choice + oct; //增加八度
choice //返回最后的结果
};

octaveAndScale.value; //choose from major scale, C4 octave
octaveAndScale.value(3); //choose from C3 octave, major scale
octaveAndScale.value(7, 2); //choose from C7 octave, whole tone scale
octaveAndScale.value(scale: 1); //choose from C4 octave, octatonic scale
)```

### 练习，闪烁

19.14. 函数练习, free, just tempered flashing

```(
//先运行这个
SynthDef("Flash",
{
arg fund = 400, decay = 4, filter = 1;
var out, harm;

out = Mix.ar(
Array.fill(7,
{
arg counter;
var partial;
partial = counter + 1;
SinOsc.ar(fund*partial) *
EnvGen.kr(Env.linen(0, 0, decay + 2),
levelScale: 1/(partial*filter)
) * max(0, LFNoise1.kr(rrand(5.0, 12.0)))
})
)*0.3; //整体音量
out = Pan2.ar(out, Rand(-1.0, 1.0));
DetectSilence.ar(out, doneAction:2);
Out.ar(0, out)
}
).play(s);
)

(
//然后这个
r = Task({
var freqFunc, pitch = 440, nextEvent;

freqFunc = {arg previousPitch;
var nextPitch, nextInterval;
nextInterval = [3/2, 2/3, 4/3, 3/4, 5/4, 4/5, 6/5, 5/6].choose;
nextPitch = (previousPitch*nextInterval).wrap(100, 1000);
nextPitch.round(0.01).post; " != ".post;
nextPitch.cpsmidi.round(1).midicps.round(0.01).postln;
nextPitch
};

{
nextEvent = [0.5, 0.25, 5, 4, 1].choose;
pitch = freqFunc.value(pitch);
Synth("Flash",
[\fund, pitch, \decay, nextEvent, \filter, rrand(1.0, 4.0)]);
//选择一个下一事件前的等待时间
nextEvent.wait;
}.loop;
}).play
)```

### 练习：函数范例

19.15. 音函数

```var freqFunc, pitches, pitch = 440, count, midiNote, nextEvent;
pitches = [60, 61, 62, 63, 64]; //申明一个音的数组
freqFunc = {
midiNote = pitches.choose; //从数组选取一个音
midiNote.midicps; // 返回那个音的cps
};

var freqFunc, pitches, pitch = 440, count, midiNote, nextEvent;
pitches = [60, 62, 64, 67, 69, 72, 74, 76]; //申明一个音的数组
count = 0; //初始化计数
freqFunc = {
midiNote = pitches.wrapAt(count); // 包裹的计数目录
if(count%30 == 29, //每九次
{pitches = pitches.scramble} //reset "pitches" to a scrambled
//verion of itself
);
count = count + 1; //递增
midiNote.midicps; //返回cps
};

// 我的最爱:
var freqFunc, pitches, pitch = 440, count, midiNote, nextEvent;
pitches = [60, 62, 64, 67, 69, 72, 74, 76].scramble;
freqFunc = {
midiNote = pitches.wrapAt(count); // 包裹计数目录
if(count%10 == 9, //every tenth time
{pitches.put(5.rand, (rrand(60, 76)))}//put a new pitch between
//65 and 75 into the array pitches
//at a random index
);
count = count + 1; //递增
midiNote.midicps; //返回cps
};``` ## 作者： ww1way

http://about.me/ww1way
{"ft_lang_label":"__label__zh","ft_lang_prob":0.65215695,"math_prob":0.9984703,"size":8241,"snap":"2019-13-2019-22","text_gpt3_token_len":5048,"char_repetition_ratio":0.113390796,"word_repetition_ratio":0.12851405,"special_character_ratio":0.41305667,"punctuation_ratio":0.31528664,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9800196,"pos_list":[0,1,2],"im_url_duplicate_count":[null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-05-26T20:22:40Z\",\"WARC-Record-ID\":\"<urn:uuid:333e05fa-a93c-4eb1-b9da-4a313b4b004f>\",\"Content-Length\":\"72671\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:a4322d7b-9b49-4be1-902a-785fbcf0ddae>\",\"WARC-Concurrent-To\":\"<urn:uuid:e641a517-dbd5-4f26-ac95-616ab24d806e>\",\"WARC-IP-Address\":\"104.24.105.47\",\"WARC-Target-URI\":\"http://learn.travelchinawith.me/sc%EF%BC%9A%E8%BF%90%E7%AE%97%E7%AC%A6%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E5%BC%95%E6%95%B0%EF%BC%8C%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%92%8C%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD/\",\"WARC-Payload-Digest\":\"sha1:QXFPANMAZBUM2JRPAGPDJP5YXN325F6A\",\"WARC-Block-Digest\":\"sha1:ISBFTAITB3V6RTBO7FPEPEANEYVM7UW7\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-22/CC-MAIN-2019-22_segments_1558232259452.84_warc_CC-MAIN-20190526185417-20190526211417-00247.warc.gz\"}"}