Windows Phone 8中MediaElement的音量控制
在Windows Phone 8上使用MediaElement的时候发现一个很奇怪的现象。按照MSDN的说法,MediaElement的Volume属性可以通过设置01之间的值来设置媒体音量(0为最小音量,1为最大音量),其默认值为0.5。然而在实际的使用中发现其默认值并不是如MSDN中所说的0.5而是1,且音量并不随着Volume从0到1均匀变化。在00.7之间声音很小几乎听不见,0.7之后开始有明显的声音,且在0.75~1.0这个区间内改变Volume的值音量随Volume的变化明显。
由此看来,音量(z)随Volume属性的值(y)的变化的函数z = g(y)的函数图像近似于指数函数图像沿y轴负方向移动一个单位(因为g(0) = 0)。对于用户来说通过滑动一个范围为0~1的音量条来调节音量,通常用户所期望的是音量(z)能随着音量条的值(x)以一次函数z=h(x)均匀变化,而非以指数函数变化。
由于要改变MediaElement的音量只能通过设置Volume属性来达到,因此需要找到一个合适的转换函数f(x) = y满足z = g(y) = g(f(x)) = h(x) = kx,(其中k为大于1的常数)。
因为g(y)的图像近似于指数函数图像沿y轴负方向移动一个单位,所以设g(y)=a^y – 1 = (e^(lna))^y – 1 = e^(ylna) – 1。
因为y的定义域为[0,1],所以z = h(x) = g(y)的值域为[0,e^lna – 1]。
因为h(x) = kx,且k>1,x的定义域为[0,1]。所以h(1) = e^(lna) – 1 = k。即h(x) = x(e^(lna) – 1)。
因为 h(x) = g(y)
=> x(e^(lna) – 1) = e^(ylna) – 1
=> x(e^(lna) – 1) + 1 = e^(ylna)
=> x(e^(lna) – 1) + 1 = e^(f(x)lna)
两边以e为底取对数
=> ln(x(e^(lna) – 1) + 1) = f(x)lna
=> f(x) = ln(x(e^(lna) – 1) + 1) / lna
令lna = c
=> f(x) = ln(x(e^c – 1) + 1) / c
至此便求得函数f(x),要确定常量c的值,需能够测得和量化音量z的最大值zmax。ln(zmax)即为c。若不具备此条件可以通过尝试不同的常数来得到一个较为合适的值。本文以c = 9.21045为例,对应的zmax约为10000。
1 |
|
f(x)和g(x)的函数定义如下:
1 | double g(double y) |
以x = 1.0 0.9 0.8 … 0.1 0.0求g(f(x))进行验证。
1 | int main() |
输出
1 | x = 1.000000 f(x) = 1.000000 g(f(x)) = 10000.094412 |
从输出可以看出所求得的函数f(x)使得音量z随着x以一次函数均匀变化。
在Windows Phone 8中应用这种转换。XAML
1 | <MediaElement x:Name="mediaElement"/> |
C#
1 | private void OnVolumeSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) |