謎の楽器

キー入力が使えるということがわかったので、鍵盤楽器のようなものを作ってみた。

(

// 音源
SynthDef("wave", {|note,amp|
f = note.lag(0.02).midicps;
g = amp.lag(0.2);
o = SinOsc.ar(f)!2*g;
Out.ar(0,o/2);
}).store;

// 音源はじめる
s.sendMsg(\s_new, "wave", 800);

// GUI
~wd = JSCWindow( "keystroke", Rect( 0, 0, 100, 100 ) );
~wd.view.canFocus = true;
~wd.view.focus;
~wd.front;

~t0 = JSCTextField( ~wd, Rect( 10, 10, 100, 20 ));
~t0.stringColor = Color.black;
~t0.value = "notenum";

~t1 = JSCTextField( ~wd, Rect( 10, 40, 100, 20 ));
~t1.stringColor = Color.black;
~t1.value = "unicode";

// 終了処理
~quit = {
	Task({
		s.sendMsg(\n_set, 800, \amp, 0);
		0.5.wait;
		s.sendMsg(\n_free, 800);
		"quit".postln;
	}).play;
};

// 配列など
~note = 60;
~mode = [1,2,3,4,5];
~key = [49,50,51,52,53,54,55,56,57,48];
~keyval = [4,3,2,1,0,5,6,7,8,9];
~amp = 0;

// キー操作
~wd.view.keyDownAction = {
	|view, char, modifiers, unicode, keycode|

	k = unicode;
	v = 0;
	b = 0;

	~t1.valueAction = k;

	~key.size.do{|i|	// 配列indexをさがす
		if( k == ~key[i], {
			v = ~keyval[i];
			b = 1;
		});
	};

	if( b == 1, {		// 数字キーで音程を上下
		n = ~mode[v%~mode.size];
		if( v<5, {	// '1~5'は下行、'6~0'は上行
			n = n*(-1);
		});
		~note = ~note + n;
		~t0.valueAction = ~note;
		s.sendMsg(\n_set, 800, \note, ~note);
		~note = max(min(~note,96),36);
	});

	switch( k,
		13, {		// ENTERで音を出す・止める
			~amp = ~amp+1%2;
			s.sendMsg(\n_set, 800, \amp, ~amp);
		},
		27, {		// ESCで終了処理
			~wd.close;
			~quit.();
		}
	);
};

)                                                    

とりあえず最低限の機能しかないのだが、これの画期的なところは「直前の音に音程を足し引きして演奏する」というもので、演奏に使うキーは11個、使える音程は半音〜4度の5種類しかないが、幅広い音域がカバーでき、派手な跳躍を無視すれば世の中の大概のメロディーは弾けるんじゃねえのと思われる。演奏している様がレジ打ちに似ていることからレジ式と名付けたい(一個のレジスタに対してひたすら加算しているとも言う)。


もちろん、

~mode = [0.5, 1, 2.5, 4.5, 6.5];

上のような謎の音階を設定しても気持ち悪い楽しいかも知れない。