見出し画像

05.変数(SuperCollider)

今回は”変数”について書きます。

その名前から、奇数とか偶数みたいな数字の仲間かなと思いがちですがそうではないです。
変数は、何でも入れられる”箱”のようなもので、とても便利ですし長いコードを見やすくしてくれます。

英語ではvariableと呼ばれるようです。

[03.フィルター]の回で、ノコギリ波をフィルターに通したときのコードを使います。

{ RLPF.ar(Saw.ar(220, 0.3)!2, 1000, 0.1, 0.3 )}.play;

これを、変数を使って見やすくします。

(
{
	a = Saw.ar(220, 0.3)!2;
	RLPF.ar(a, 1000, 0.1, 0.3)}.play;
)

aが変数です。※詳細は後述します。

どうでしょうか。これだとRLPFのパラメータが4個で、そのひとつ目がaというふうにシンプルに見えます。
そのかわりにあらかじめaの中身がSaw.ar(220, 0.3)!2だということを書いています。

この、書く順番は大切です。SuperColliderの処理は上の行から順に行われるので、下記のように上下逆に書いてしまうと、

(
{
RLPF.ar(a, 1000, 0.1, 0.3)}.play;
a = Saw.ar(220, 0.3)!2;
)

SuperColliderが正しく理解してくれません。SuperColliderがRLPF.ar(a, 1000, 0.1, 0.3)の行を読んだ時点で「aって何?」となるのです。

なので、順番的にはまずaの中身を書いてあげる必要があります。
また、{波カッコ}の内側に書く必要があります。
そうすることで、SuperColliderはRLPF.ar(a, 1000, 0.1, 0.3)を正しく処理してくれます。

繰り返しになりますが、このaのことを変数と言います。
アルファベット小文字1文字を変数として使うことができます。
a〜z、ただしsを除く25文字です。
sを除く理由は後述します。

RLPFの4個のパラメータを全部変数を使って書くこともできます。

(
{ 
	a = Saw.ar(220, 0.3)!2;
	b = 1000;
	c = 0.1;
	d = 0.3;
	RLPF.ar(a, b, c, d)}.play;
)


RLPF.ar(a, b, c, d)それぞれのパラメータに変数が割り当てられていて、これもアリですよね。見やすいです。

今はSawをひとつRLPFに通してるだけなのでそこまでしなくても、と思ってしまいますが、複雑な音を作ろうとするほどこんな感じでたくさんの変数を使うようになってきます。

箱に入れる


ところで変数を扱うとき、「=」の部分は「等しい」とは考えず「中に入れる」と考えるのが正しい捉え方です。
aという箱の中に数値を入れる、という感じです。

上記の例だと、
箱aの中に、Saw.ar(220, 0.3)!2を入れ、
箱bの中に、1000を入れ、
箱cの中に、0.1を入れ、
箱dの中に、0.3を入れました。

=の右側のものを変数という箱に入れる


「=」という記号ではなく「←」とかだと感覚的にわかりやすかったですよね。
a ← Saw.ar(220, 0.3)!2;
b ← 1000;
c ← 0.1;
d ← 0.3;
のような。。
でも「=」と書きます。

※先ほど「aという箱の中に数値を入れる」と書いてしまったのですが、実際には数値だけでなく何でも入れることができます。
(すでにSaw.arを入れてますしね・・・)
今後たくさん例を出していきます。

変数名を自由につける方法


今までの例ではアルファベット小文字1文字を変数名にしていましたが、変数名を自由につける方法もあります。

以下の例では、変数名にsignalという名前をつけました。
名前のつけ方は「行の頭にvarを置いて、変数名とその中に入れるものを書く」だけです。

varはvariableの略です。

名前はなんでも自由につけることができますが、アルファベットの小文字から始まる必要があります。(下記の例だとsignalのsが小文字。)

(
{
	var signal = Saw.ar(220, 0.3)!2;
	RLPF.ar(signal, 1000, 0.1, 0.3)}.play;
)
signalという箱の中にSaw.ar(220, 0.3)!2を入れる。

アルファベット1文字のときと違うのが、varがあることです。
varと書くことで「ここから先は変数名ですよ」とSuperColliderに教えています。「ひと区切り」を意味するセミコロン(;)を忘れずに。

名前をつけたほうが、変数に何を入れたかがわかりやすいですよね。
特に下記のように、複数の変数が存在する場合は顕著です。

変数名を複数つける場合は、下記のように各行にvarをつけてもよいですし

(
{ 
	var signal = Saw.ar(220, 0.3)!2;
	var cutFreq = 1000;
	var res = 0.1;
	var vol = 0.3;
	RLPF.ar(signal, cutFreq, res, vol)}.play;
)

中に入れるものが短いなら、下記の「行2」ようにカンマで区切ってもよいです。

(
{ 
	var signal = Saw.ar(220, 0.3)!2;//行1
	var cutFreq=1000, res=0.1, vol=0.3;//行2
	RLPF.ar(signal, cutFreq, res, vol)}.play;
)

いずれの場合も、varの行は{波カッコ}の内側に書く必要があります。

最初にまとめて変数の名前だけ決めておいてそれぞれの中身を次に書く、というやり方もアリです。僕自身はこっちのやり方のほうが多いかなと思います。

(
{ 
	var signal, cutFreq, res, vol;//行1
	signal = Saw.ar(220, 0.3)!2;//行2
	cutFreq = 1000;
	res = 0.1;
	vol = 0.3;
	RLPF.ar(signal, cutFreq, res, vol)}.play;
)


行1で、最初に箱の名前だけ決めています。
この段階ではsignal, cutFreq, res, volは名前だけが付いた空き箱です。
そのあと、それぞれの箱に中身を入れています。
行2以降で中身を入れるときにはvarは要らないです。
signal, cutFreq, res, volが変数名だということを、行1でSuperColliderはもう知っているからです。

あと気をつけたいポイントを書いておきます。

例えば下記のようにcutFreqの箱に数字を入れ直した場合、

(
{ 
	var signal, cutFreq, res, vol;//行1
	signal = Saw.ar(220, 0.3)!2;
	cutFreq = 1000;//行3
	res = 0.1;
	vol = 0.3;
	cutFreq = 400;//行6
	RLPF.ar(signal, cutFreq, res, vol)}.play;
)

cutFreqは400として処理されます。
SuperColliderは上から順番に処理していきます。
行1で箱を作る。
行2でsignalにノコギリ波を入れる。
行3でcutFreqに1000を入れる。
行4でres, 行5でvolに数値を入れる。
行6でcutFreqに400を入れる。(前に何が入っていたかは関係ナシ)

なので結果的にcutFreqには400が入っている状態でRLPF.ar(signal, cutFreq, res, vol)は処理されます。

この、変数の中身の入れ直しができる仕様はとても便利に使える場面もあります。
今後、そういった例も出てきます。

varを使って変数名を書く方法では変数の中身が分かりやすいという利点があり、アルファベット小文字1文字を変数に使う場合はvarの行が不要なので簡易的に使えるという利点もあり、両方ともよく使われます。

ところで変数名をアルファベット小文字1文字にする場合はsを除く、と前述しました。
その理由は、sはSuperColliderのシステム内の変数としてデフォルトでServerが登録されているためです。

例えば

s.boot;

を実行すると、サーバが起動します。
※ServerメニューからBoot Serverを選択することや、command+bすることと同じです。

bootは「起動せよ」という内容のメソッドです。このbootメソッドはサーバに対してだけ有効です。
他にもsに指示できるメソッドはいくつかあります。のちのち紹介します。


改めて

[03.フィルター]の回で使った最後のコードを変数を使って書いてみました。
変数sigの中で変数freqを使う、という形になっています。

(
{ var freq, cutFreq, sig;
	freq=MouseX.kr(110, 880);
	cutFreq=MouseY.kr(20, 2000);
	sig=Saw.ar(freq, 0.3)!2;
	RLPF.ar(sig, cutFreq, 0.1, 0.3)}.play;
)

マウスをクリックしない状態でぐるぐる回すと音色とピッチが変化します。

おまけ

あとひとつ、最後におまけ情報です。

変数に、{波カッコ}全体を入れることもできます。
僕自身はそれほど使う場面は無いのですがネットで情報をあさると結構出てくるので(ヘルプドキュメントとかにも出てきます)、情報として書いておきます。

下記を1行ずつ実行してみてください。

x = {SinOsc.ar(220, 0, 0.3)!2};

x.play;

1行目で変数xに処理する信号を入れています。
変数xに対してplayメソッドを送っています。

また、「生成した信号をプレイしている状態」を変数に入れることもできます。

y = {SinOsc.ar(330, 0, 0.3)!2}.play;

こうすると、これを実行したあと音を止めるとき、変数yに対してメソッドを送ることで止めることができます。

y.free;

(もちろんコマンド&ピリオドでも止まります。)

今日はここで終わります。

次回はエンベロープについて書きたいと考えています。
エンベロープを使うと、コードを見やすくするために変数が欠かせません。

その後はおおよそ下記のような流れですすめていこうと思います。

・エンベロープ(EnvGen)、ゲート
・音源を作ってシーケンスする(SymthDefとPattern)
・ステレオ、パンニング
・サンプル波形(wavファイル)を鳴らす
・LFO、変調
・エフェクト、バス
・録音
・methodいろいろ、Classいろいろ

今日のまとめ

・変数の中身は{波カッコ}内、変数を使う前に書く。
 {波カッコ}外に書く方法もありますが、それはまた後日。
・アルファベット小文字1文字を変数として使う場合はa〜zが使える。
 ただしsを除く。sにはServerが入っています。
・変数に名前をつけるときはvarを行頭に書き、変数名はアルファベット小文字で始まるもの。


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


この記事が気に入ったらサポートをしてみませんか?