Env.new().asSignal(自作波形をオシレータとして鳴らす)
Envを使って自分で描いた波形をオシレーターとして鳴らすことができます。
こんな波形や
こんな波形など比較的自由に描くことができます。
前回・前々回で使ったこのフォーマットを利用します。
(
~bfr = Buffer.alloc(s, 2048);
~sig = Signal.sineFill(1024, [1, 0.5, 0.3, 0.25, 0.2]);
~wt = ~sig.asWavetable;
~bfr.loadCollection(~wt);
)
この2行目を変更します。
下記のような感じです。
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env.new([0, 1, -1, 0], [0.01, 0.1, 1.0], [4, -4, -4]);
~sig = ~sig.asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)
2行目でエンベロープを書いて、3行目のasSignalでSignal化しています。
ちなみにEnv.newの.newは省略できるので、そしてEnvに対して直接.asSignalできるので、下記のように書くこともできます。
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env([0, 1, -1, 0], [0.01, 0.1, 1.0], [4, 0, -4]).asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)
asSignalの引数1024はBuffer.allocで確保した数のちょうど半分である必要があります。(ここでは2048に対して1024)
Signal化したあとは、これまでのようにWavetable化してバッファに入れています。
※Envの各パラメータについてはあとで詳細を見ていきます。
作った波形を視覚的に確認するには.plotします。
~sig.plot;
OSCクラスで鳴らして出音を確認できます。
{Osc.ar(~bfr.bufnum, 220, 0, 0.3)!2}.play;
Pbindで鳴らしてみます。
ここでは少しデチューンさせてフィルターに入れています。
そしてフィルターのカットオフにMouseXを、レゾナンスをMouseYに割り当てているので、実行したら(再生したら)マウスを画面上で(クリックしないまま)上下左右にぐるぐる動かしてみるとフィルターの具合が変化します。
(
// reverb bus
~rvbBus = Bus.new(s, 2);
// reverb
SynthDef.new(\fvrb, {
var eff, src;
src = In.ar(~rvbBus, 2);
eff = FreeVerb2.ar(src[0], src[1], 0.05, 2);
Out.ar(0, eff);
}).add;
// buffer tone
SynthDef.new(\envTone, {
arg freq=220, gate=1, det=1.0;
var sig, env;
env = EnvGen.kr(Env.adsr(0.01, 0.2, 0.7, 0.02), gate, doneAction:2);
sig = Osc.ar(~bfr.bufnum,[freq-det, freq+det]);
sig = RLPF.ar(sig, MouseX.kr(20, 3000), MouseY.kr(0.05, 1.0));
Out.ar(~rvbBus, sig * env);
}).add;
// sequence
~seq = Pbind(
\instrument, \envTone,
\midinote, Pseq([48, 55, 60, 67, 72, 60, 55, 67]-12, inf),
\dur, Pseq([0.25], inf),
\sustain, Pseq([0.25, 0.1, 0.1, 0.1], inf),
);
~eff_seq = Pfx(~seq, \fvrb).play(TempoClock(130/60));
)
さて、Env.newについて詳しく見ていきます。
各パラメータは下記の内容です。
Env.new([グラフのポイント], [ポイント間の距離(割合)], [ポイント間のカーブ])
例えば下記のように書くと
~sig = Env([-1, 1, -1], [1.0, 0.5], [0]);
「-1」「1」「-1」という3つのポイントを直線で繋ぎます。
「-1から1の間」と「1から-1の間」の長さが違うのは[1.0, 0.5]としているからです。
[1.0, 0.5]はポイント間の比率なので[2.0, 0.5]などと書くともっと両者の長さに差が生まれます。
~sig = Env([-1, 1, -1], [2.0, 0.5], [0]);
~sig = Env([-1, 1, -1], [2.0, 0.1], [0]);
鳴らしてみるとノコギリ波のような音が鳴ります。
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env([-1, 1, -1], [2.0, 0.1], [0]).asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)
※Pbindシーケンスは先ほどと同じものを利用できます。(上記を実行したあとPbindを実行。)
ポイント間の比率が全部同じでよければ数値はひとつだけでかまいません。(下記では1.0とだけ記入しています。)
~sig = Env([-1, 1, -1], [1.0], [0]);
これは
~sig = Env([-1, 1, -1], [1.0, 1.0], [0]);
と同じ意味です。
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env([-1, 1, -1], [1.0], [0]).asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)
鳴らしてみると先ほどより倍音の少ない音が鳴ります。
いま[0]にしている一番右の数値はポイント間を直線にするかカーブにするかのパラメータです。
数値をプラスにしたときとマイナスにしたときの比較。
(
~sig1 = Env([-1, 1, -1], [1.0], [3]);
~sig2 = Env([-1, 1, -1], [1.0], [-3]);
~sig1.plot;
~sig2.plot;
)
数値が小さいほどカーブが緩やかに、大きいほどカーブが急になります。
もちろんポイントごとに違うカーブを設定できます。
~sig = Env([-1, 1, -1], [1.0], [1, -8]);
ポイントはいくつでも追加できます。
~sig = Env([0, 1, -0.9, 0.7, -0.5, 0], [1.0], [10, -10, 5, -10, -5]);
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env([0, 1, -0.9, 0.7, -0.5, 0], [0.1, 0.2, 0.2, 0.5, 1.0], [10, -10, 5, -10, -5]).asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)
[グラフのポイント]のパラメータには、プラス値とマイナス値をほどよく混ぜておくのをお勧めします。上記の[0, 1, -0.9, 0.7, -0.5, 0]にあたる部分です。
プラス値ばかりやマイナス値ばかりだとDCオフセットが起きた状態になってしまいますので。
また、ポイントの最初と最後の値は同じにしておくと波形をループさせたときのつながりがよくなります。
こんなふうにあえてはずすのもアリですけども、不要な倍音が発生しないほうがいいという場合は最初と最後の値が同じかどうかを見直すのがよいと思います。
~sig = Env([-1, 1, -1, 1], [1.0], [0]);
<目次へ>
https://note.com/sc3/n/nb08177c4c011