見出し画像

ネットで見かけるコード記述法


ネットでコードをあさっていると、見慣れない記述に出会います。
SuperColliderは(同じ音を出すにしても)色々な書き方ができるので。
今日は、このnote記事では紹介したことないけどネットではよく見る書き方、を4つほど紹介しようと思います。

ex1を題材のコードとします。

//ex1
(
SynthDef(\tri, {
	arg freq=440, atk=0.01, gate=1;
	var sig, env, amp=0.3;
	env = EnvGen.kr(Env.asr(atk, 1, 0.01, 1), gate, doneAction:2);
	sig = LFTri.ar(freq);
	sig = Pan2.ar(sig, 0) * env;
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)

command + Bでブートサーバして、カッコ内をcommand + Returnキーで実行すると音が鳴ります。
ドレミファを繰り返すコードです。
Command + ピリオドで音が止まります。


arg(アーギュメント)


ex1のargの行ですが

arg freq=440, atk=0.01, gate=1;

この↑行は・・・

| freq=440, atk=0.01, gate=1 |

こう↑書いても同じ意味です。
この書き方は、よく見かけます。

(
SynthDef(\tri, {
	| freq=440, atk=0.01, gate=1 |
	var sig, env, amp=0.3;
	env = EnvGen.kr(Env.asr(atk, 1, 0.01, 1), gate, doneAction:2);
	sig = LFTri.ar(freq);
	sig = Pan2.ar(sig, 0) * env;
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)


そしてもうひとつ、よく見かける、ex2のargの書き方の紹介です。

//ex2
(
SynthDef(\tri, {
	var sig, env, amp=0.3;
	env = EnvGen.kr(Env.asr(\atk.kr(0.01), 1, 0.01, 1), \gate.kr(1), doneAction:2);
	sig = LFTri.ar(\freq.ar(440)) * env;
	sig = Pan2.ar(sig, 0);
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)

カッコ内をcommand + Returnキーで実行するとex1と同じ音が鳴りますが、このコードには「arg」の行がありません。(|と|で囲ってもいません。)

これはargの行を省略できる書き方です。
ex1でargの行に書いていた変数が全て本文の中だけに存在しています。

例えばfreqを例にとると、argの行に書いていた代わりに、freqを使いたい場所で\付きで記述してます。

そして.arに続けてカッコ内に初期値を書き込んでます。この場合は440です。

arg freq=440 & 使う場所でfreq

とex1では書いていたのを

使う場所で\freq.ar(440)

とex2では書いている

ということです。

\atkも\gateも同じく、です。

arを使うかkrを使うかについては・・・
.arなら、サンプリングレートと同じきめ細かさ
.krなら、少し(arの64分の1)荒くなる代わりにcpuの処理負荷が減ります。

(arとkrの違いについては、こちらの僕の過去記事でも書いています。)
公式のヘルプページにも。)

この\付きのargの書き方についてはEli Fieldsteelさんの動画でも解説されてます。
https://youtu.be/Hw0MXqKMpGA?list=PLPYzvS8A_rTb8YheJZVKTo9aRs7xnCYYT&t=1158

この、「arg行を省略する書き方」で利点があるのは、やっぱり変数を2箇所に書く必要がないってことですかね。
例えばex2に加えて、「アウトプットもargにしてPbindからコントロールできるようにしよう」と思った時、ex3のように、使いたい場所にそのまま書き込むだけで実現するので。この書き方に慣れたら、わざわざargの行を作るより速い、って思うようになるかもしれません。

//ex3
(
SynthDef(\tri, {
	var sig, env, amp=0.3;
	env = EnvGen.kr(Env.asr(\atk.kr(0.01), 1, 0.01, 1), \gate.kr(1), doneAction:2);
	sig = LFTri.ar(\freq.ar(440)) * env;
	// sig = Pan2.ar(sig, 0);
	Out.ar(\out.ir(0), sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
	\out, Pseq([0,1],inf),
).play(TempoClock(60/60));
)

ところでex3の\out.ir(0)では、.arでも.krでもなく.irを使いました。
アウトプットは連続的に変化するパラメータではないので。
そういうものには.irを使うのが通例のようです。
ただし\out.kr(0)と書いても動作します。

他にも、サンプリングレートやバスの出力先など、"最初に一度決めたら連続的に変更するものではないもの"をirにするようです。
ちなみに
arはオーディオレート
krはコントロールレート
irはイニシャルレート
の略です。


doneActionのDone.freeSelf


この書き方もよく見かけます。
ex4は、Done.freeSelfを使ってex1を書き換えたものです。
envの行の、doneActionの部分だけが違いです。

//ex4
(
SynthDef(\tri, {
	arg freq=440, atk=0.01, gate=1;
	var sig, env, amp=0.3;
	env = EnvGen.kr(Env.asr(atk, 1, 0.01, 1), gate, doneAction:Done.freeSelf);
	sig = LFTri.ar(freq);
	sig = Pan2.ar(sig, 0) * env;
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)

これについては、そのまんまの意味です。
もともとdoneActionの2はDone.freeSelfを2という一文字で表現できるようにしてあるだけなので、2と書かずにそのまま書いた、という形です。

https://doc.sccode.org/Classes/Done.html

ヘルプページの記述
Done.freeSelf;

これ↑を実行するとpost windowに2と表示されます。

2と書くほうがシンプルなのに、わざわざDone.freeSelfと書く理由は僕にはわかりません。それでもよく見かけるんですよね・・・見た目にわかりやすいということでしょうね。

(参考)doneActionについて書いている過去記事
https://note.com/sc3/n/ncfa9297ea01b



dbamp


この書き方もよく見かけます。

//ex5
(
SynthDef(\tri, {
	arg freq=440, atk=0.01, gate=1;
	var sig, env, amp= -10.dbamp;
	env = EnvGen.kr(Env.asr(atk, 1, 0.01, 1), gate, doneAction:2);
	sig = LFTri.ar(freq);
	sig = Pan2.ar(sig, 0) * env;
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)

音量を0.3などの数値で書かずに、デシベル表記で書くことができます。

amp= -10.dbamp
の部分です。

SuperColliderを使って音の実験をしたり、何かの計測をしたり、みたいな人はこの書き方がいいのかも。

いつも使ってる0.3などの数値をデジベル表記で確認するには下記を実行します。

0.3.ampdb;

Post windowに結果が表示されます。

逆に、-10db(デシベル)って、superColliderで数値記述するといくつなのかを知りたい場合は下記を実行します。

-10.dbamp;

(参考)
デジベルではMAXの値(これ以上大きい音だと歪んでしまう値)は0なので、下記を実行するとPost windowに1.0と表示されます。

0.dbamp;

https://doc.sccode.org/Classes/SimpleNumber.html

ヘルプページの記述


さて、このdbampをargなどコード内に書くときには注意すべきポイントがあります。

ex5では以下のように、=と-の間にスペースを入れています。
amp= -10.dbamp

これには理由があって、
amp=-10.dbamp
のようにスペース無しで書いてしまうと、エラーになってしまうからなんです。
=と-をくっつけてしまうと違う意味になってしまうので。(変数に初期値を入れるところでは使えないです。すみません、詳細は省きます。)

=と-がくっつくのを防ぐために、スペースを入れる代わりに次のように書くのでもOKです。
amp=(-10.dbamp)


EnvGenの省略


エンベロープを使うには通常、作ったエンベロープをEnvGenに入れますが、
(参考過去記事
ex6の書き方だと、EnvGenを省略することができます。

//ex6
(
SynthDef(\tri, {
	arg freq=440, atk=0.01, gate=1;
	var sig, env, amp=0.3;
	env = Env.asr(atk, 1, 0.01, 1).kr(2, gate);
	sig = LFTri.ar(freq);
	sig = Pan2.ar(sig, 0) * env;
	Out.ar(0, sig * amp);
}).add;

Pbind(
	\instrument, \tri,
	\midinote, Pseq([60,62,64,65],inf),
	\atk, Pseq([0.01,0.6],inf),
	\dur, 1,
).play(TempoClock(60/60));
)

コードの見た目がスッキリしていいですね。
この書き方の利点は、もちろんEnvGenを省略できることですが、もう一つあります。
Env.asr(atk, 1, 0.01, 1).kr(2, gate);
の、.kr()の、ひとつ目の引数(パラメータ)がdoneActionであるということです。なのでわざわざdoneAction:2と書く必要は無く、2だけでOKなんです。そして次の引数はgateです。

https://doc.sccode.org/Classes/Env.html(Inherited class methodsの項目。)


※EnvGenだとdoneActionは6つ目の引数。

https://doc.sccode.org/Classes/EnvGen.html


僕は、最初にEnvGenに入れる方法で最初に覚えてしまったのでなんとなくEnvGenを使うのがしっくり来てしまい、いつもEnvGenを使ってます。


今日は、以上です。


<目次へ>
https://note.com/sc3/n/nb08177c4c011


いいなと思ったら応援しよう!