在Windows Mobile/Windows CE 6.0上逐渐增加系统音量

3

我正在尝试使用coredll.dll中的waveOutSetVolume逐渐增加音频音量,从静音(或接近静音)到最大。

我找到的大多数代码示例都显示了一些预定义的关闭、低、正常、中、高和非常高的设置点,如下所示:

Public Enum Volumes As Integer
    OFF = 0
    LOW = 858993459
    NORMAL = 1717986918
    MEDIUM = -1717986919
    HIGH = -858993460
    VERY_HIGH = -1
End Enum

在我的尝试中,我尝试从0开始使用1200作为增量逐步提高音量。这只会增加右声道的音量。大约在66000左右,所有音频都会回到静音状态,然后再次开始增加,但只在右声道上。
上面列出的常数确实影响了我所希望或期望的两个通道。但是,我不清楚如何逐渐从0过渡到858993459,然后再次逐渐从858993459过渡到1717986918等。
我怀疑我的理解中有一些根本性的问题。
我正在使用VB.Net和Visual Studio 2008中的.Net Compact Framework 3.5。如果您有C#的解决方案,我也可以接受。
编辑: 从我现在所读的内容来看,上面列出的枚举值是基于十六进制的,其中00000000是最低音量,而FFFFFFFF是最高音量。这仍然对我没有太多帮助,因为我不确定如何逐渐增加VB.Net中的十六进制,并同时将其转换为整数。我也不清楚仅仅在这里增加十六进制是否会导致同时在所有/两个通道上增加音量,或者我是否仍然会遇到我目前遇到的立体声问题。
我正在使用此类:
Public Class VolumeControl
    <DllImport("coredll.dll", SetLastError:=True)> _
    Friend Shared Function waveOutSetVolume(ByVal device As IntPtr, ByVal volume As Integer) As Integer
    End Function

    <DllImport("coredll.dll", SetLastError:=True)> _
    Friend Shared Function waveOutGetVolume(ByVal device As IntPtr, ByRef volume As Integer) As Integer
    End Function

    Public Shared Property Volume() As Integer
        Get
            Dim v As Integer = CInt(0)
            waveOutGetVolume(IntPtr.Zero, v)
            Return v
        End Get
        Set(ByVal value As Integer)
            waveOutSetVolume(IntPtr.Zero, value)
        End Set
    End Property
End Class

好的,这里是一些API文档,但在这种情况下,它对我来说并没有太多意义。低位字和高位字是什么,它们如何存在于单个值中?

· dwVolume
新的音量设置。低位字包含左声道音量设置,高位字包含右声道设置。值为0xFFFF表示完全音量,而值为0x0000表示静音。 如果设备不支持左右声道音量控制,则dwVolume的低位字指定音量级别,忽略高位字。

1个回答

5

首先,让我稍微道歉,因为我将使用C#进行回答。现在还太早了,而且我还没有喝咖啡,所以我的VB语言翻译器还没有启动。

枚举值用十六进制表示更加清晰易懂。

Public Enum Volumes As Integer  
    OFF = &H00000000  
    LOW = &H33333333
    NORMAL = &H66666666  
    MEDIUM = &H99999999  
    HIGH = &HCCCCCCCC  
    VERY_HIGH = &HFFFFFFFF  
End Enum  

因此,音量是一个DWORD,它对应于32位整数。这是完整的音量:

0xFFFFFFFF

它被“分割”成两个WORD(16位)通道 - 左和右 - 在概念上像这样:

0xFFFF 0xFFFF

显然,左声道具有更高的“位值”,因此为了将它们合并,它实际上看起来像这样:

0xFFFF0000 [left] | 0x0000FFFF [right] == 0xffffffff

如果您在单个更改中具有低且非零的值,例如0x0099,则立体声值如下:

0x00990099

因此,要分别连续提高两个通道的音量,请从零循环到ushort.MaxValue(0xffff),将DWORD(32位uint)中的两个WORD(16位ushort)设置为相同的值:

UInt16 left;
UInt16 right;
UInt32 both;

for(int i = 0 ; i < ushort.MaxValue ; i++)
{
    left = i << 16; // left shift it to the upper 16 bits
    right = i;
    both = left | right;
    waveOutSetVolue(both);
    Thread.Sleep(10);
}

显然,您需要调整睡眠暂停时间,并可能需要调整 i 的步长,以获得所需效果。通常,这不是一个线性进展,因此简单地递增 i 可能需要更复杂的操作,但您应该明白这个概念。 编辑1 现在我喝了咖啡:
Dim left As UInt16
Dim right As UInt16
Dim both As UInt32

For i As Integer = 0 To UShort.MaxValue - 1
    ' left shift it to the upper 16 bits
    left = i << 16  
    right = i
    both = left | right
    waveOutSetVolume(both)
    Thread.Sleep(10)
Next

似乎我的移位操作有问题。当变量“left”定义为16位时,你能把i向左移动16位吗?此外,使用“And”运算符似乎不能将我的值连接到“both”变量中,这与我的预期不符。 - HK1
好的,当我在API调用中将我的音量参数声明为UInt32而不是像以前一样使用整数时,我的一些问题得到了解决。waveOutSetVolume(ByVal device As IntPtr, ByVal volume As UInt32) As Integer - HK1
为什么要用"And"和"&"?你必须使用"Or"和"|"。在你的代码中,“both”总是0。 - Vahid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接