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