見出し画像

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

前回は下記のようなSynthDefを作りました。

(
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;
)

今回はこの音色をシーケンスさせます。


Pbind


音色をシーケンスさせるにはPbindクラスを使います。
書き方のフォーマットは、ざっくり書くと下記のようなものです。

Pbind.new(\instrument, \音色名, \note, 音符, \dur, 音長).play;

改行を入れて見やすくします。
(横に長かった1行にただ改行を入れただけなので各行の終わりに;は不要です。)

(
Pbind.new(
\instrument, \音色名,
\note, 音符,
\dur, 音長
).play;
)

あとは音色名、音符、音長の部分に必要なものを入れていきます。
音色名は先ほど(前編にて)SynthDefでsynth1とつけました。

音符はノートナンバーで、0が中央ド(midinoteの60)です。

音長は(60秒に音符を60回鳴らすのが1ですので)まずは1としておきます。

(
Pbind.new(
	\instrument, \synth1, 
	\note, 0, 
	\dur, 1
).play;
)

※SynthDefで音色名をダブルクォートで書いた人は、ここでもダブルクォートを使います。
\instrument, “synth1”,


鳴らしてみる。


まずSynthDefの部分を実行して、synth1という音色をサーバにaddします(置きます)。
そして、 Pbindの部分を実行してみましょう。
中央ドの音が繰り返し鳴ります!
鳴りましたでしょうか。

ドの繰り返しから脱却、メロディーにするにはこのように書きます。

(
Pbind.new(
	\instrument, \synth1, 
	\note, Pseq([0, 2, 4, 5], 2), 
	\dur, 1
).play;
)

SynthDefは一度実行したらサーバに置かれっぱなしですので、今回はPbindだけの実行でよいです。(サーバを一度落としたら(ソフトを終了したら)もう一度SynthDefを実行する(.addする)必要がありますが。)

今度は「ド、レ、ミ、ファ」と2回繰り返しました。
このように音を連続で鳴らすにはPseqを使います。

ちなみに中央ドより低いものは、例えば\note, Pseq([0, -1, -3, -5], 2)と書くと「ド、シ、ラ、ソ」になります。

noteはmidinoteで指定することもできます。
僕はいつもmidinoteを使います。中央ドは60です。

dur


durは、durationの略です。
durを0.5にすると、音符ごとの間隔が半分になります。
上記の\durを0.5に変更するとシーケンス全体をテンポアップさせた印象になりますし、次のように音符ごとにdurを変えることもできます。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], 2), 
	\dur, Pseq([1, 0.5, 0.5, 1], 2)
).play;
)

\midinoteのPseqの[角カッコ]と\durのPseqの[角カッコ]の数字が順番通りに対応しているわけです。(ノート60が1の音長、ノート62が0.5の音長、ノート64が0.5 の音長、ノート65が1の音長、という具合)


ここまで来たら、もうあとは自分の好きなようにアレンジしていけますね。ちなみに、midinoteとdurどちらかのループ回数が短い場合、短い方に合わせられて止まります。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], 2), 
	\dur, Pseq([1, 0.5, 0.5, 1], 1)
).play;
)

延々とループ再生したい場合は、繰り返し回数の箇所にinfと書きます。 ※infはinfiniteの略

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5, 1], inf)
).play;
)

コマンド&ピリオドするまで止まりません。


そもそものテンポ(bpm)を変えたい場合は下記のようにします。
playメソッドにパラメータ(TempoClockというクラス)を与えてあげる形です。次の例ではbpmを100にしてみています。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5, 1], inf)
).play(TempoClock.new(100/60));
)

デフォルトでは60/60、つまり1でしたが、分子(上記の100のところ)を他の数字にすることでbpmを変更できます。


さて、ちょっと面白い実験をやってみます。
Pseqの[角カッコ]内の数字の個数がmidinoteとdurで違っていたらどうなるか。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5], inf)
).play(TempoClock.new(100/60));
)

midinoteを4つ、durを3つにしてみました。
ずーっと聴いていると、その規則性を感じられるのではないでしょうか。
音程は4個の繰り返しで、durは3個の繰り返し再生になります。
こういったトリッキーなことができるのもSuperColliderの面白さです。


他のパラメータもargする


ところで、argに指定しておけばSynthDef中のどんなパラメータも外から扱うことができますので、実験してみます。

先ほどのSynthDefではエンベロープのパラメータをデフォルトで使っていました。

//先ほどのコードそのままのものです。
//Env.percにパラメータ(引数)が設定されていないので、
//デフォルト値でEnv.percが作られていることがわかります。
(
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;
)

このコードに変更を加えてEnv.percのアタックとリリースタイムをargに登録してシーケンス(Pbind)から扱えるようにします。
下記の例ではargで指定した名前をatkとrlsとしていますが、attack, releaseでも何でもいいです。
僕は意味さえわかれば3文字くらいがいいなと思うのでatk, rlsにしました。

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

形的にはこれでいいのですが、arg指定するときに何か値も指定してあげておきます。

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

そうしておくとSynth.newを使って簡易的に再生テストしたときにfreq, atk, rlsをそれぞれその値で鳴らしてくれるんです。

Synth.new(\synth1);

もし初期値を書かないままSynth.new(\synth1);を実行すると、Synth.newは鳴らす音色はsynth1だとわかるものの、その音程は(freqとしか書かれておらず何ヘルツなのか)わかりません。

前編の時のテスト再生では下記のようにfreqを440と指定して書いたので、その音程で鳴らしてくれたのでした。

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

Env.percのatk, rlsも初期値以外の数値でテスト確認したい場合は下記のように \名前, 値 のペアで指定すればOKです。(アタックタイムを少し長めにしてみました。ゆるやかなアタックの音が聴こえるはずです。)

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


midicpsメソッド


ちょっとしたTipsですが、この時のfreq、midinoteで聴きたい時もありますよね。そういう場合、

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

このように書いてしまうと60ヘルツの音を再生してしまいますので、midicpsというメソッドを使います。(midi to cicle per secの略です。)

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

上記コードは60という数字に対して「midi to cpsせよ」と指示しています。ちなみに次の行だけ実行するとPost windowに変換後のヘルツが表示されます。

60.midicps;

Pbind.newの中で\noteや\midinoteが直接使えたのは、Pbindの中にそういう変換機能が備わっているからなんです。便利です。
ただ、その変換機能を使うにはピッチのarg名をfreqにしておかないといけません。

ちなみに、Pbindで\noteや\midinoteを使わず、下記のようにもともとのarg名\freqで音程を奏でることも可能です。

(
Pbind.new(
	\instrument, \synth1, 
	\freq, Pseq([220, 330, 440, 660], 2), 
	\dur, 1
).play;
)


他のパラメータもargする(続き)


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

これをPbindで鳴らすという話の途中でした。
一度このコードを実行してsynth1をaddしておきましょう。

Pbindの書き方。
書き方は、\arg名, \パラメータ というペアを追加していけばよいだけです。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5, 1], inf),
	\atk, 0.5,
).play;
)

まだrlsは指定していないですが、指定しなければデフォルト値(この場合0.8)が採用されます。実行してみてください。
次はrlsも追加して、さらに音符ごとにatkの値を変えてみます。次のコードを実行してみてください。

(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5, 1], inf),
	\atk, Pseq([0.5, 0.01, 0.01, 0.8], inf),
	\rls, 0.3,
).play;
)

と、こんな具合にSynthDef内のパラメータであればarg名をつけてあげることで、Pbindからコントロールできます。

エンベロープのアタックやリリースを外からいじることはあまり無いかもしれないですが、SynthDef内にフィルターや波形自体を変化するパラメータが含まれれば、音色を変化させながらシーケンスさせることができます。


doneAction:2


最後に、今日使ったSynthDefに再び注目します。

s.plotTree;

これを実行してNodeTreeウィンドウを表示させた状態で、今日のどのPbindでもいいので再生してみてほしいです。
音が再生されるたびにsynth1という名前の白い四角が現れて消えます。
又は白い四角が消えずとも、synth1の左側に表示されるナンバーが1音ごとに更新されます。

1音再生されるたびにSC3がsynth1という音声信号を処理し(白い四角とナンバー表示)、処理終了していますよ(白い四角とナンバーが消える)、という意味で、これはdoneAction:2が機能している証拠です。

EnvGenをcommand+dしてヘルプウィンドウで調べてみます。
この中で重要な(いつも使う)パラメータは、
envelope
gate
doneAction
です。

gateについては次回説明します。
envelopeは今日はEnv.percを使いました。
doneActionは「エンベロープが終了したら現在行っている処理をどうするか」というパラメータです。

デフォルト値は0で、0は「何もしない」という意味です。
今日は2を使いましたが、2は「free the enclosing synth(シンセを解放する)」です。

なので、先ほどNodeTreeで見たように、1音ずつ処理されては解放することを繰り返していました。

これが初期値の0だったらどうなるでしょうか、実験します。
下記のSynthDefを改めて実行し(Post windowに a SynthDef と表示されるのを確認)、次にPbindを実行します。

(
SynthDef.new(\synth1, {
	arg freq=440, atk=0.01, rls=0.8;
	var sig, env;
	env = EnvGen.kr(Env.perc(atk, rls));
	sig = Saw.ar(freq, 0.3)!2;
	Out.ar(0, sig * env)
}).add;
)
(
Pbind.new(
	\instrument, \synth1, 
	\midinote, Pseq([60, 62, 64, 65], inf), 
	\dur, Pseq([1, 0.5, 0.5, 1], inf),
	\atk, 0.01,
	\rls, 0.5,
).play;
)

コマンド&ピリオドで音を止めるまで、NodeTree内に白い四角が増え続けます。

リリースタイムが終わってエンベロープが終了してもシンセを解放しないため、白い四角が残り続けるのです。ボリュームゼロのまま音が鳴り続けている、そんな状態です。

音量のエンベロープを使うときにはdoneAction:2にする必要があることがわかりました。

普段意識して使うのは0か2(パラメータ指定するほとんどの場合が2)だと思うのですが、その他の数値はこのようになっています。参考に。https://doc.sccode.org/Classes/Done.html

.newの省略


次回はキーオン/キーオフ情報(ゲートON/OFF)を扱うエンベロープについて書きます。
Pbindも、より複雑なことができるようになります。

ところで今日出て来た
 音源に名前をつけるSynthDef.new
 それを簡易的に鳴らすSynth.new
 それをシーケンスして鳴らすPbind.new
は、すべて.newの記述を省略することができます。

むしろ.newは書かないのが慣例のようなので、今後はシンプルに.newを省いて書きます。


今回のまとめ


・Pbind.new(\instrument, \音色名, \note, 音符, \dur, 音長, \引数名, 数値).play;
・Pseq([数値, 数値, 数値], 繰り返し回数)
・Pbind内での音程の指定はnoteかmidinoteで指定すれば自動的にfreqに変換してくれる。(freqで直接指定することもできる。)
・Pbindの再生テンポは、playメソッドの引数で設定する。.play(TempoClock.new(100/60)
・argでつける引数名はアルファベット小文字で始まれば何でもよい
・midicpsは、MIDIノートナンバーを周波数に変換してくれるメソッド
・EnvGen.krの引数doneActionに2を指定すると、SC3はエンベロープ終了後にシンセを解放する(音声信号の処理をやめる)。1音のエンベロープが終了するたびにシンセを解放しないと(音声信号の処理をやめないと)、音は無音のまま再生され続けることになる。
・SynthDef.new、Synth.new、Pbind.newの.newは省略できる。

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

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