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

HK1*_*HK1 3 c# vb.net compact-framework windows-ce

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

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

Public Enum Volumes As Integer
    OFF = 0
    LOW = 858993459
    NORMAL = 1717986918
    MEDIUM = -1717986919
    HIGH = -858993460
    VERY_HIGH = -1
End Enum
Run Code Online (Sandbox Code Playgroud)

在我的尝试中,我尝试使用 1200 作为我的增量从 0 逐步提高音量。这只会增加右声道的音量。在 66000 左右的某个地方,所有音频都恢复静音并再次开始增加,但仅在正确的通道上。

正如我所希望或预期的那样,上面列出的常量确实会影响两个通道。但是我不清楚如何逐渐从 0 过渡到 858993459,然后再逐渐从 858993459 过渡到 1717986918,等等。

我怀疑从根本上我不明白这是如何工作的。

我在 Visual Studio 2008 中使用 VB.Net 和 .Net Compact Framework 3.5。如果你有 C# 的解决方案,我没问题。

编辑:
根据我现在阅读的内容,上面列出的枚举值基于十六进制,其中 00000000 是可能的最低音量,FFFFFFFF 是可能的最高音量。这仍然对我没有多大帮助,因为我不确定如何在 VB.Net 中逐渐增加十六进制并同时将其转换为整数。我也不清楚仅在此处增加 Hex 是否会导致所有/两个通道的音量同时增加,或者我是否仍然存在立体声问题。

我正在使用这个类:

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
Run Code Online (Sandbox Code Playgroud)

好的,这里有一些 API 文档,在这个特定的上下文中对我来说没有多大意义。什么是低位词和高位词,它们如何同时存在于一个值中?

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

cta*_*cke 5

首先,让我稍微道歉,因为我将用 C# 回答。太早了,我没有喝咖啡,所以我的 VB 心理翻译器还没有被激活。

枚举值在十六进制中看起来更好,更容易理解。

Public Enum Volumes As Integer  
    OFF = &H00000000  
    LOW = &H33333333
    NORMAL = &H66666666  
    MEDIUM = &H99999999  
    HIGH = &HCCCCCCCC  
    VERY_HIGH = &HFFFFFFFF  
End Enum  
Run Code Online (Sandbox Code Playgroud)

所以卷是一个 DWORD,映射到一个 32 位整数。所以这是完整的卷:

0xFFFFFFFF

这被“拆分”为 WORD(16 位)通道 - 左右 - 概念上是这样的:

0xFFFF 0xFFFF

显然,左声道具有更高的“位置值”,因此将它们组合起来确实是这样的:

0xFFFF0000[左] && 0x0000FFFF[右] == 0xffffffff

如果您在一次更改中有一个低的非零值,例如 0x0099,那么立体声值将如下所示:

0x00990099

因此,要持续以相同的量提升两个通道,您需要从零循环到 ushort.MaxValue (0xffff),将 DWORD(32 位 uint)中的两个 WORDS(16 位 ushorts)设置为相同的值:

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);
}
Run Code Online (Sandbox Code Playgroud)

显然,您需要调整睡眠暂停以及可能会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 And right
    waveOutSetVolue(both)
    Thread.Sleep(10)
Next
Run Code Online (Sandbox Code Playgroud)