GStreamer Player のボリュームを直線的に変更したい。
GtkHScale の値を直で渡すと曲線になって使いにくい、DirectShow はもっと酷かったけど。
音量のデシベルは非常にややこしい。
GStreamer マニュアルの GstStreamVolumeFormat 以下にも 20 * log10 (val) とある。
実は私の Cinema という Windows 用 DirectShow プレイヤーは手抜きをしていて…
DirectShow ボリュームは最大 0、無音 -10,000 をデシベル単位でということなのですが…
1 2 3 4 5 6 7 | void CDirectA::SetVolume( int nVolume) { double d = pow (( double )(nVolume * 2), 2.0); m_nVolume = static_cast < int >(-d); if (pBasicAudio) pBasicAudio->put_Volume(m_nVolume); }</ int > |
というベキ乗を利用してなんとなく似たようなカーブにしている。
ぶっちゃけ WMP とは全然カーブが違うんだが面倒だということで(ぉい!
GStreamer ボリュームは最大 100.0、無音 0.0 なのでコレを Y901x で真似るには
1 2 3 | def on_volume_value_changed( self , widget, event = None ): val = widget.get_value() * * 2 / 10000.0 self .player.set_property( "volume" , val) |
とやってみたけど完全に違う、GStreamer では同じ手は使えないようだ。
キチンと調べないといけないみたい、Totem はどうやっているかコードを漁る。
bacon-video-widget-gst-0.10.c の bacon_video_widget_set_volume 関数で
GST_STREAM_VOLUME_FORMAT_CUBIC を指定している、この型と相互変換が必要か。
gststreamvolume を pygst から利用するには c ヘッダが gst/interfaces 以下にあるので
1 2 | import gst dir (gst.interfaces) |
みたいにやれば関数が一覧されるので探ってみる。
stream_volume_set_volume は流石に使えないようだけど convert はできるようだ。
CLAMP 関数も必要かな C言語でCLAMP(a,b,c) | OKWave
一行なのでラムダ式を使えと言われそうだが CLAMP という関数名も覚書に使いたい。
1 2 3 4 5 6 7 8 9 10 11 | def set_volume( self , value): v = gst.interfaces.stream_volume_convert_volume( gst.interfaces.STREAM_VOLUME_FORMAT_CUBIC, gst.interfaces.STREAM_VOLUME_FORMAT_LINEAR, value) def clamp(a,b,c): return min ( max (a,b),c) v = clamp(v, 0.0 , 1.0 ) self .player.set_property( "volume" , v) def on_volume_value_changed( self , widget, event = None ): self .set_volume(widget.get_value() / 100.0 ) |
おっし、これで Totem とまったく同じ音量カーブになった。
CUBIC を LINEAR に変換すればいいのね、実はいまいちよく解っていなかったり(ぉい!
もう少し Debug して Y901x の Playbin2 化 version 0.3 はなんとかなりそう。