見出し画像

07.作った音色をシーケンスする:前編(SuperCollider)

これまでは一定の音程の音を鳴らして止めるだけでしたが、今回は「作った音色でメロディーを奏でる」ということをやりたいと思います。

音色を定義するSynthDef


まずは音色に名前をつけます。
それにはSynthDefクラスを使います。

SynthDef.new(\name, {function}).add;

SynthDef.newは(\音色名、と、{どんな音色})というパラメータで構成されています。
{波カッコ}の中身はいつものやつです。

ここではsynth1という名前をつけます。

SynthDef.new(\synth1, {Out.ar(0, signal)}).add;

バックスラッシュ(\)は必ず必要です。「ここから後ろが名前だよ」とSC3に教えてあげる意味があります。下記のように”ダブルクォート”で囲んでもOKです。どちらでも好きな方で。

SynthDef.new(“synth1”, {Out.ar(0, signal)}).add;

「{波カッコ}の中身はいつものやつ」と書きましたが、{波カッコ}内に見慣れないものがありますね。Saw.arやSinOsc.arではなくOut.arというふうになっています。

実はSynthDefの{波カッコ}内ではまずアウトプット(その音色をどのアウトから出すのか)を設定してあげなければなりません。それでOutクラスを使います。

Out.arは(どのアウトから, どの音色を)というパラメータを持っています。
上記では「アウト0から」と設定しています。そしてsignalのところに「どの音色を」を書きます。つまりこんな感じです。

SynthDef.new(\synth1,{Out.ar(0, Saw.ar(220, 0.3)!2)}).add;

いつものノコギリ波を設定してみました。
そして.addは、「サーバに置きなさい」という指示です。
※サーバはSC3内にある「音声信号を処理する部分」です。ですのでこのコードを実行する前にはcommand+bでサーバを起動させておく必要があります。
アウト0は、左スピーカーです。
アウト0とだけ書いておけば、(!2があるので)それがアウト1にも複製されて両チャンネルから音が出ます。

前回覚えたエンベロープをあてがってみます。
コードが長くなるので、改行を入れて変数を使います。

(
SynthDef.new(\synth1, {
	var sig, env;
	env = EnvGen.kr(Env.perc, doneAction:2);
	sig = Saw.ar(220, 0.3)!2;
	Out.ar(0, sig * env)
}).add;
)

※doneAction:2については後述します。

これで準備ができました。実行してみます。
サーバにaddしただけなので音は出ませんがPost windowに

a SynthDef

と表示されて、SynthDefが無事に実行されたことがわかります。
この音色を簡易的に鳴らすにはSynthクラスを使います。下記を実行してみてください。

Synth.new(\synth1);

実行するたびにsynth1という音が鳴りますね。

さて、このsynth1でメロディーを奏でるために少しコードを改造する必要があるのですが・・・その前に、ちょっと脱線して用語について書いておきます。

function


これまで{波カッコ}内に処理させたいものを入れてきました。
中に処理させたいものが入った状態の{波カッコ}をfunctionと呼びます。
functionを説明するならば、、、「数値など何かを渡してあげると、何かしらの処理をして結果を出してくれるもの」です。
これまでも、いくつかのパラメータを渡してノコギリ波やサイン派をスピーカーから出してくれました。

音ではない例、簡単な例でfunctionをもう少し説明します。(音色をシーケンスさせるのに必要なので。。ちょっと長い脱線になりますが。。)

例えば、a=5, b=2のとき、a+bは7ですよね。
下記を1行ずつ実行すると、SuperColliderもPost windowに答えを出してくれます。

a=5;
b=2;
a+b;

aとbは変数です。なので数学で出てくるイコールとは違い、
aという箱、bという箱にそれぞれ5と2を入れています。

さて、では処理させたい全体を{波カッコ}に入れて、さらに.valueという指示を与えてみます。

{a=5; b=2; a+b;}.value;

これも実行すると答えを出してくれます。
※valueは、{function}に対して「処理結果を出して!」と指示するメソッドです。音声信号の{function}に対してplayと指示したのと同じです。

5や2を他の数字に入れ替えてもちゃんと答えを出します。(当たりまえ。。)

この5と2についてですが、function自体を変更せずに数字だけを与えることで計算処理できたら、もっと他の計算にも役に立ちますよね。

その方法があります。下記のようにします。

{arg a, b; a+b;}.value(5, 2);

argというワードが初めて出てきました。
varなら使ったことがありますよね。変数名を指定するときにvarを使いました。それと使い方は同じです。ただ、
 varは「名前のついた箱」でしたが
 argは「”functionの外から箱の中身を入れ替えることができる”名前のついた箱」です。
valueの右側の(カッコ)内の数字を自由に変えて実行してみてください。

argはvarと同じく箱の名前を指定するワードなので、aやbのアルファベット1文字だけでなく、自由な名前も指定できます。(ただしアルファベット小文字で始まるもの)

{arg akira, naoki; (akira+naoki)/2;}.value(55, 52);

式も変えてみました。アキラ君とナオキ君の体重の平均値を出す式のイメージです。
55と52の数字を入れ替えることで、いつでも二人の体重の平均を求めることができます。

argの数に制限はありませんので三人目の追加もできます。

{arg akira, naoki, taro; (akira+naoki+taro)/3;}.value(55, 52, 50);

functionがどんなに複雑なものであってもvalueにパラメータを与えてあげることでSuperColliderはfunctionを処理して答えを出してくれます。

— memo —
argはargumentの略で、日本語では”引数”と呼ばれます。
functionは、日本語では”関数”です。

計算の順序


計算式をSuperColliderで使う時、ひとつ気をつけるべき点があります。SuperColliderは律儀に左から順に計算します。

5+2*10;

これ、学校では2*10が20、それに5を足して、答えは25と習いますよね。SuperColliderは左から順に計算するので、答えは70と出します。
学校で習ったように計算させたければ下記のように書きます。(実行してみてください。)

5+(2*10);

↑こうすると(カッコ)から先に計算してくれますので答えは25と出します。

arg(引数)


さて、さてさて、脱線が大変長くなりすみませんでした。
下記の音色をシーケンスさせる、という話の途中でした。

(
SynthDef.new(\synth1, {
	var sig, env;
	env = EnvGen.kr(Env.perc, doneAction:2);
	sig = Saw.ar(220, 0.3)!2;
	Out.ar(0, sig * env)
}).add;
)

ですがこのSynthDef、もう一手間だけ手を加える必要があります。
この音色を使ってメロディーを奏でたい、つまりこのfunctionの外からピッチを操作したいわけです。なのでその準備をします。

(
SynthDef.new(\synth1, {
	arg freq;
	var sig, env;
	env = EnvGen.kr(Env.perc, doneAction:2);
	sig = Saw.ar(freq, 0.3)!2;
	Out.ar(0, sig * env)
}).add;
)

先ほどアキラ君とナオキ君の体重の平均を求めたのと同じ要領で、argを使ってノコギリ波の音程をfreqという名前で登録しました。
これでこの音色の音程を外からコントロールできます。
※argで指定する名前は何でも良いのですが、ピッチを指定するときはfreqにしておくと便利です。その理由は後述します。

先ほど使ったSynthクラスで簡易的にテストしてみましょう。

Synth.new(\synth1, [\freq, 440]);

[argで指定した名前, 鳴らしたいピッチ]というのを書き加えています。
音程の数値を変えて実行すると指定のピッチで鳴ります。
これでSynthDefの外からピッチを指定して音を鳴らす準備が整いました。

ちょっと長くなってきたので、ここで一区切りします。
続きは「後編」にて。

よろしくお願いします。

今回のまとめ

・音色を定義する(音色に名前をつけて、アウトプットを決める)クラス、SynthDef
・SynthDefの音色を簡易的に再生確認するクラス、Synth
・{波カッコ}はfunction(関数)
 function(関数)は「数値など何かを渡してあげると、何かしらの処理をして結果を出してくれるもの」
・arg名(引数名)をつけておけばfunction(関数)の外側から数値を指定することができる
・arg(引数)もvar(変数)と同じく、名前をつけるときはアルファベット小文字からはじまるものにする必要がある
・SuperColliderは計算式を左から順に計算する

<目次>にも今回のリンクを作っておきました。https://note.com/sc3/n/nb08177c4c011

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