gateとt_gate(arg名いろいろ)
今日は下記のコードを題材に arg名について書きます。
書き終えて振り返ると、説明がずいぶん長くなってしまいました。
書いてるのは下記の順序ですので、興味があるところあたりをまず読んでいただくのも良いかなと思います。
・arg名は自由につけられる。(以下の場合を除く。)
・音源の周波数を音階でコントロールしたいならarg名をfreqに。
・ノートON/OFF(Envの動作開始と停止)を受け取るarg名はgateに。
・Envが持続音系ではない時は、arg名をt_gateに。
・音源の音量のarg名はampにしておくと便利な時がある。
[ex1]
// まずブートサーバしておきます。
(
SynthDef(\testTri, {
arg freq=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
).play(TempoClock(60/60));
)
// 音を止めるには、コマンド+ピリオドです。
テンポ60で2拍に1回、ドの音を繰り返し鳴らす単純なコードです。
argに freq と gate を登録して、 Pbind側から音程とノートON/OFFをコントロールできるようにしています。
*ノートON/OFFとは、Pbindを鍵盤での演奏に見立てて
「鍵盤を押す(ON:音を出す)、鍵盤を離す(OFF:音を止める)」
ということです。
さて、次はこのコードを色々といじってみます。
テンポ60で2拍に1回ドの音を繰り返し鳴らす、というところまでは同じですが、1音ごとに音色やエンベロープが変わっていくようにしてみました。
[ex2]
(
SynthDef(\testTri, {
arg freq=440, gate=1, amp=0.3, atk=0.01, dcy=0.3, sus=0.6, rls=0.3, modf=2, pls=0.1, modr=50;
var sig, env, mod, mod2;
env = EnvGen.kr(Env.adsr(atk, dcy, sus, rls), gate, doneAction:2);
mod = SinOsc.ar(modf).range(-1*modr, modr);
mod2 = LFPulse.ar(pls);
sig = LFTri.ar(freq + mod) * mod2;
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
\amp, 0.3,
\atk, Pseq([0.01, 2.0, 1.0, 0.3], inf),
\dcy, Pseq([0.2, 0.3, 0.8, 0.1], inf),
\sus, Pseq([0.6, 1, 0.2, 0], inf),
\modf, Pseq([0, 0.1, 100, 400, 900], inf),
\modr, Pseq([50, 400], inf),
\pls, Pseq([0.1, 0.1, 0.1, 0.1, 2, 4, 6], inf),
).play(TempoClock(60/60));
)
// 音を止めるには、コマンド+ピリオドです。
SynthDefに音色をモジュレートするmodとmod2を加えて、さらにmodやmod2内のパラメータやadsrエンベロープの各パラメータにarg名をつけて、argに登録しています。
登録したそれらのパラメータをPbindから操作しています。
SuperColliderは様々なパラメータにarg名をつけてPbindからコントロール可能なので、アイデア次第で色んなことができてしまいます。
arg名は自由につけられる
ここでarg名に着目します。
arg名は何でも好きなようにつけることができます。
[ex2]ではアタックをatkとしていますが、attackというarg名にしてもいいですし、p01とかでもOK、(アルファベットの小文字で始まるものなら)何でも。
modfなんて僕が勝手に”モジュレートフリケンシー”を略したものです。
そして自分でつけたarg名のパラメータを、Pbind側からコントロールできます。
Pbind側のkey名とarg名が一致していれば機能するんです。
*書く順番はarg名とkey名で一致してなくてもいいです。また、argに登録し
たけどPbindで結局使わないというのも問題ありません。その時は初期値で鳴らされます。上の例で言うとrlsは0.3で鳴らされます。
ところで、いつもお馴染みのarg名である freq と gate はPbind側に見当たりませんね。
ご存知の通り、音程は\midinoteで指定してるので・・・じゃfreqの役割は?と疑問に思ってしまいますが、そこにはSuperColliderの便利な機能が隠されています。
freq
コードの例をシンプルなコードに戻します。
([ex1]とコードの内容は同じです。)
[ex3]
(
SynthDef(\testTri, {
arg freq=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
).play(TempoClock(60/60));
)
freqはLFTri.arの周波数のargなので、本来なら単位はHzです。
だけど音符を周波数で書くのは大変なので、Pbind側で
\midinote
の指定をすればSuperColliderがHzに変換してSynthDefに伝えてくれています。
これはarg名をfreqとしておくことで受けられる恩恵です。
\midinote(中央ドが60)の代わりに
\note(中央ドが0)という指定方法もできます。
[ex4]
(
SynthDef(\testTri, {
arg freq=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\note, Pseq([0, 2, 0, -1], inf),
\dur, 2,
).play(TempoClock(60/60));
)
試しに、freqの代わりにpitchというarg名を使って実験してみます。
[ex5]
(
SynthDef(\testTri, {
arg pitch=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
sig = LFTri.ar(pitch);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
).play(TempoClock(60/60));
)
音が鳴ることは鳴りますが、さっきまでとは違う音程ですよね。これ「ド」ではなく440Hzの「ラ」ですね。
arg名をpitchにしたために、\midinoteからの"60"という指示をSynthDefが受け取れずに、初期値440Hzのまま再生されてます。
では、Pbind側もkey名をpitchにしてみたらどうでしょう?
[ex6]
(
SynthDef(\testTri, {
arg pitch=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
sig = LFTri.ar(pitch);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\pitch, 60,
\dur, 2,
).play(TempoClock(60/60));
)
これも音が鳴ることは鳴りますが、小さいスピーカーからだと聞こえないくらい低い音ですね。これ60Hzの音が鳴ってしまってます。
それもそのはず。Pbind側で"\pitchは60"と指定してますから。SynthDefに対して「鳴らす音は60Hzだよ」と伝えています。
つまり、周波数(Hz)で音楽を作りたいなら、freq以外のarg名でもOKです。
音階のついたシーケンスを作るなら、音程を指定するargは「freq」としておくと便利!
*補足*
arg名をfreqにしておいて、Pbind側のkey名を
\freq
にすることでも、周波数で鳴らすことができます。
gateとt_gate
gateというarg名も、freqと同じように特別なものです。
ですがfreqと違うのは、gateの代わりに他のオリジナルarg名は使えないってところです。
(freqの場合は、周波数で音楽を作るならpitchなど他のarg名でもOKでしたが、gateはgateに代わるものはナシ。)
なのですが、gateの仲間でt_gateというのがありまして、t_gateの出番はタマにあります。
どのような場合か。
エンベロープが持続音系ではない時です。
例えば
Env.adsr
Env.asr
こういった持続音系エンベロープは、鍵盤を押したら(ノートONしたら)その鍵盤を離すまで音が鳴り続けます。そして鍵盤を離したら(ノートOFFしたら)音がリリースして止まります。いわゆるオルガン系のエンベロープです。こういう時はgateで良いのですが・・・
エンベロープが
Env.perc
Env.linen
などの、減衰系(ベル系)の時は、鍵盤を押したら(ノートONしたら)一定時間でエンベロープの減衰が起こり、鍵盤を離そうが離すまいが(ノートOFFしようがしまいが)エンベロープの終了とともに音も止まります。
このエンベロープを使う時は、arg名をt_gateにするのがベターです。
arg名をt_gateにしておくと、「鍵盤を一瞬だけ押した」状態になります。ゲートタイムが極小、です。
いつ鍵盤を離しても一定の時間で音が消えていくんだから、鍵盤を押すのは一瞬だけでいいんじゃない?というわけです。
(ちょっと記述がweb上に見つからないんですが、ノートONのあと、確か1/44100(サンプリング周波数)*64(SC3のコントロールレート)秒後にはノートOFFだったと思います。0.0015秒後です。
t_gateのtはtriggerの略だったと思います。トリガーゲートの略でt_gateです。)
[ex7]
(
SynthDef(\testTri, {
arg freq=440, t_gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.perc(0.01, 1.0), t_gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
).play(TempoClock(60/60));
)
"ベター"と書いたのは、gateでも"音は鳴る状態"になってしまうところです。
次のコードを実行してみてください。
[ex8]
(
SynthDef(\testTri, {
arg freq=440, gate=1;
var sig, env, amp=0.3;
env = EnvGen.kr(Env.perc(0.01, 1.0), gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
).play(TempoClock(60/60));
)
これは[ex7]のコードのt_gateをgateに置き換えたものです。確かに、同じように音は鳴っています。ですが、post windowを見ると、ひとつの音が鳴り終わるたびに何かメッセージを出してきてます。
これは、gateが2拍に1回(テンポ60なので2秒に1回)音を止めようとしてるんだけど、Env.percによってアタックタイム含めて1.01秒後には音が消えているので「止める音が見当たらないよ」と言っています。
t_gateを使えば、t_gateのゲートタイムは一瞬なので、その問題はなくなるというわけです。
* * * 補足 * * *
エンベロープ再生中(エンベロープを発動した一瞬後)にノートOFFの指示を受けることができるということで・・・それでもエンベロープは止まらず最後まで再生されるのですが・・・とりあえず形式的には音の再生中に指示を受けることはできたので、それでpost windwにはメッセージは出ない。・・・ということはエンベロープ発動中にノートOFFを受けられれば良いわけで、[ex8]のコードのPbindの部分に1行追加して以下のようにしてあげると
post windowのメッセージは出ません。全部の音長を\sustainで極小にしてるので。これ、やってることはt_gateと同じです。
t_gateを採用していれば、極小の\sustainを設定しなくてもいいので楽、という話です。
* * * * * * * * * * * *
そういうわけで、前回の曲の時もリズム系のSynthDefではt_gateを使っていました。エンベロープがEnv.percだったので。
amp
もうひとつ、ampというarg名、これも音量のarg名として便利に使える機能を持ってます。
Pbind側からkey名をもちろん\ampとして、音量変化を加えることができますが・・・
[ex9]
// 1音ごとに音量が変化します。
(
SynthDef(\testTri, {
arg freq=440, t_gate=1, amp=0.3;
var sig, env;
env = EnvGen.kr(Env.perc(0.01, 1.0), t_gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
\amp, Pseq([0.3, 0.2, 0.1, 0.3], 1),
).play(TempoClock(60/60));
)
デシベルでの指定もできます。
[ex10]
// 1音ごとに音量が変化します。(デシベルで指定)
(
SynthDef(\testTri, {
arg freq=440, t_gate=1, amp=0.3;
var sig, env;
env = EnvGen.kr(Env.perc(0.01, 1.0), t_gate, doneAction:2);
sig = LFTri.ar(freq);
sig = Pan2.ar(sig, 0) * env;
Out.ar(0, sig * amp);
}).add;
Pbind(
\instrument, \testTri,
\midinote, 60,
\dur, 2,
\db, Pseq([-12, -18, -24, -12], 1),
).play(TempoClock(60/60));
)
*デシベルは0が最大ですので、数値の入力時には注意を!(\dbを0にするとかなり大きな音で鳴ると思いますので、耳やスピーカーを痛めないように注意です。
ampを他のarg名にしている場合は(0〜1のamp数値は機能しますが)デシベルでの指定はできません。
何か音の実験・テストでSupderColliderを使う場合には役立ちそうな機能です。
今回は説明文が長くなってしまったのですが
・arg名は自由につけられる。(以下の場合を除く。)
・音源の周波数を音階でコントロールしたいならarg名をfreqに。
・ノートON/OFF(Envの動作開始と停止)を受け取るarg名はgateに。
・Envが持続音系ではない時は、arg名をt_gateに。
・音源の音量のarg名はampにしておくと便利な時がある。
ということでした!
<目次へ>
https://note.com/sc3/n/nb08177c4c011