SuperCollider: Wave TableシンセとGuiの連携(2)

今度は複数のウェーブテーブルを作って、波形を動かしてみる。

こんな感じ。

ひとつのウェーブテーブルを作成して音を鳴らすまでは前回の記事に。

複数スライダーのGuiを作成する

今回は波形を描く用のスライダーを3つ作成する。MulthSliderViewを3つ分作って変数mに格納し、そのあとcollectでm配列のアイテム(各スライダー)ごとに描画の設定をしている。

var slide=3, dot=100, width=350, height=80;
w = Window.new.front;
m = Array.fill(slide,{arg i;
	MultiSliderView(w, Rect(0, i*height, width, height))});
m.collect({arg item;
	item.value_(Array.fill(dot, {0.5}));
	item.elasticMode=1;
	item.thumbSize = 2;
	item.background_(Color(1,1,1,0.2));
});

zeroラインの描画

各スライダーの背景に0.0位置のラインをPenで描画

w.drawFunc = {
	slide.do({ arg i; 
            var px = (i*height)+(height/2);
            Pen.line(Point(0, px), Point(width,px));
            Pen.stroke;
	})
};

Bufferの確保

サイズ2048のBufferを3つぶん作成。allocConsecutiveを使うと連続したbufnumのBufferを作成できて便利。ここではbufnum:0から2までのBufferを作成している。

b = Buffer.allocConsecutive( slide, s, 2048, bufnum:0 );

ボタンが押された時に実行される関数を作成

前回はButtonクラスのアクションファンクションに直接書いていたが、見た目がごちゃっとするので今回は分けてみた。

やっている中身は単ウェーブテーブルの時と一緒だが、今回はbに格納されているBufferそれぞれに処理をしている。(引数のbufにはb内のアイテム(Buffer)が、iにはdoごとにイテレーションされるカウンターが入ってくる)

f = {
	b.do({ arg buf, i;
	  var cs, level, env;
          cs = ControlSpec(-1, 1, \lin, 0.00001, 0);
          level = cs.map(m[i].value); //mはスライダーの配列
          level.add(level.at(0));
          env = Env(level, 1, \sin).asSignal(1024).asWavetable;
          buf.loadCollection(env);
	})
}

関数fを実行するためのボタンを作成する。

p = Button(w, Rect(0, height*slide+20, 80, 30))
    .states_([["update"]])
    .action_({ f.value }); //関数fを実行する

バッファーのポジションを指定するためのスライダーを作る

今回は複数のバッファーに格納された複数ウェーブテーブルを混ぜて使う(使用するウェーブテーブルが入っているbufnumが0と1の場合、0.5を指定すれば0と1のウェーブテーブルがブレンドされたような波形になる⇒スムーズに波形から波形をトランスフォームさせることが可能)

今回はEZSliderクラスを使う。ControlSpecの部分でバッファーのポジションの範囲を設定している(今回はスライダーが3つなので、0~2の範囲)が、上限を2にすると何故か音が止まっちゃうので(原因はよくわからない。。)1.99までにしている。

また、アクションファンクションでSynthを格納するxにスライダーの値をセットしている。

g = EZSlider( w,                    // parent
              Rect(0,height*slide,width,20), // bounds
              " pos ",              // label
              ControlSpec(maxval:1.99),      // controlSpec
              { |ez| x.set(\pos, ez.value) } // action
)

UGenを作る

複数ウェーブテーブルを使用するにはVOscを使用する。引数posでEZSliderからバッファーのポジションを受け取る。

(
SynthDef(\wtSynth, { arg pos=0;
	var env, sn;
	sn = VOsc.ar(pos, mul:0.3);
	Out.ar(0, sn);
}).add;
)
x = Synth(\wtSynth);

全体のコード

https://github.com/rucochanman/SCLibrary/blob/master/Gui/waveTable