Apr 22, 2015

foobar2000のwsh panel modのサンプルコードその4



そろそろ飽きてきました。
『ボリュームを作ろう』がメインテーマです。
愛ってよくわからないけど傷つく感じが素敵。
裏テーマとして図形関係も書きます。

sample5.txtをインポートしてください。

Image_computer/wsh_8.png



// ==PREPROCESSOR==
// @name "Sample5 Volume"
// @author "Junya Renno"
// ==/PREPROCESSOR==

var imgpath = fb.ProfilePath+"/skin/sample/";

function RGB(r, g, b) { return (0xff000000 | (r << 16) | (g << 8) | (b)); }


var g_drag = 0;
var bar_color = RGB(151,15,13);

function on_paint(gr){
var ww = window.Width;
var wh = window.Height;
var volume =fb.Volume;
var pos =Math.exp((-(-volume-100)*Math.log(100))/100);
var x = pos * ww /100;

var bg_img = gdi.Image(imgpath+"bg.png");
var knob_img = gdi.Image(imgpath+"knob2.png");

if(x<5){x=0;}
else if(x>(ww- 5)){x= ww - 11;}
else{x-=5;}

gr.DrawImage(bg_img,0,0,ww,10,0,0,bg_img.Width-10,10);
gr.FillSolidRect(0,2,x,8,bar_color);
gr.DrawImage(knob_img,x,0,11,11,0,0,11,11);

}

function on_mouse_lbtn_down(x,y){
g_drag = 1;
}

function on_mouse_lbtn_up(x,y){
on_mouse_move(x,y);
g_drag = 0;
}

function on_mouse_move(x,y){
if(g_drag){
var pos = x * 100 / window.Width;
var v =100-(Math.log(pos)*100)/Math.log(100);
v = (v<0) ? 0 : (v<100) ? v : 100;
v = -v;
if(fb.Volume != v)
fb.Volume = v;
}
}

function on_mouse_wheel(delta){
if(delta>0)
fb.VolumeUp();
else
fb.VolumeDown();
}
function on_volume_change(val){
window.Repaint();
}



基本的な考え方として、fb.volumeに現在の値が入っているので、それを取ってきて表示し、新しい値をfb.volumeに入れればOK。

問題はこの部分。

var volume =fb.Volume;
var pos =Math.exp((-(-volume-100)*Math.log(100))/100);
var x = pos * ww /100;


ボリュームの値をxに変換しているわけですが、Wsh Panel Modについてくるサンプル(Volbar.txt)はもっと単純です。

var x = window.Width * ((100 + volume) / 100);


xは0~パネルの横幅の値をとります。
volumeは-100~0の値です。
どう変換するかというのが肝ですね。
ところが一つ問題がありまして、『音量は単純に比例しているわけではない』という点です。
むしろ対数であって、単純な変換の場合には音量が極端に大きくなっていく問題があるわけです。
それでこういうちょっと面倒な式にしてあるわけですね。
実際私が考えた式ではなく、monolite plusにあった式を拝借しました。(にしては偉そうだな)
理屈については小学生でも分かるデシベル(dB)の話技術レポート db(デシベルとは)とかに詳しいです。
単純な計算式のサンプルをsample6.txt、Wsh Panel Modにはhuman hearing curve(人間の聞こえ方をグラフにしたもの)をもとにしたサンプルがあったので、それを使ってsample8.txtを比較用に書きました。
試してみるのも一興でしょう。


gr.DrawImage(bg_img,0,0,ww,10,0,0,bg_img.Width-10,10);
gr.FillSolidRect(0,2,x,8,bar_color);
gr.DrawImage(knob_img,x,0,11,11,0,0,11,11);


ボリュームの描写部分です。
背景の画像を敷いて、長方形を塗りつぶし、つまみの画像を表示しています。

描画関係の命令については他に

●DrawLine(x1, y1, x2, y2, line_width, color)
線を引く。
●DrawRect(x, y, w, h, line_width, color)
長方形を描く。
●DrawRoundRect(x, y, w, h, arc_width, arc_height, line_width, color)
角の丸い長方形を描く。
●DrawEllipse(x, y, w, h, line_width, color)
楕円を描く。
●DrawPolygon(color, line_width, points)
点を線でつないだ図形を描く。pointは[x1,y1,x2,y2,...]のようなペア同士の配列。


●FillSolidRect(x, y, w, h, color)
長方形の塗りつぶし。
●FillGradRect(x, y, w, h, angle, color1, color2, focus = 1.0)
長方形で、2色を使ったグラデーションの塗りつぶし。angle=0~360,focus=0~1.0
●FillRoundRect(x, y, w, h, arc_width, arc_height, color)
角の丸い長方形の塗りつぶし。
●FillEllipse(x, y, w, h, color)
楕円の塗りつぶし。
●FillPolygon(color, fillmode, points)
点を線でつないだ図形の塗りつぶし。

などがあります。
やろうと思えばつまみも背景も直接描けるんですが、そこはデザインとの絡みです。


on_mouse_move(x,y){}で、ドラッグしていれば計算してfb.volumeにセットします。
on_mouse_wheel(delta){}ではマウスホイールの動きを感知し、ボリュームを上下させています。

こんなもんですかねえ。
次は最終回、『ドロップダウン型のボタンを作る』です。
プレイリスト関連は私もイマイチわかってないんですが、まあがんばってみましょう。


では。


追記:

v = (v<0) ? 0 : (v<100) ? v : 100;

みたいなのは三項演算子といいまして、

if( v<0 ) v=0;
else if(v<100) v=v;
else v=100;

と同等。
なんとなくこれ使うと『俺プログラム書けるぜ!』みたいな雰囲気を出せるので、覚えておくと得かも。



 
エントリを編集・・・

wikieditish メッセージ: Ready to edit this entry.
















A quick preview will be rendered here when you click "Preview" button.