我需要获取声卡输出的当前音量。
有什么想法吗?
您可以在 Vista 和 Win 7 的 CoreAudio API 中使用IAudioMeterInformation获取这些值。
NAudio中提供了托管包装器(从 MMDevice 获取 AudioMeterInformation)。
当我正在开发一个(尚未发布......)应用程序时,我解决了这个问题,该应用程序在没有其他声音时启动某种“电梯音乐”。
遵循马克希思给出的精彩技巧,我得到了我想要的:
using NAudio.CoreAudioApi;
MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
string currVolume = "MasterPeakVolume : " + defaultDevice.AudioMeterInformation.MasterPeakValue.ToString();
static int PlayerVolume()
{
RecordPlayer rp = new RecordPlayer();
rp.PlayerID = -1;
int playerVolume = rp.PlayerVolume;
return playerVolume;
}
来自修改后的 C# 中的麦克风音量文章
在 MSDN 信息中查找:
这是“常见”信息。C# 可能有更方便的方法(我不知道)。
也许 winmm.dll 可以帮助你:
来自 EDDYKT (VB):
Private Const HIGHEST_VOLUME_SETTING = 100 '%
Private Const AUX_MAPPER = -1&
Private Const MAXPNAMELEN = 32
Private Const AUXCAPS_CDAUDIO = 1 ' audio from internal CD-ROM drive
Private Const AUXCAPS_AUXIN = 2 ' audio from auxiliary input jacks
Private Const AUXCAPS_VOLUME = &H1 ' supports volume control
Private Const AUXCAPS_LRVOLUME = &H2 ' separate left-right volume control
Private Const MMSYSERR_NOERROR = 0
Private Const MMSYSERR_BASE = 0
Private Const MMSYSERR_BADDEVICEID = (MMSYSERR_BASE + 2)
Private Type AUXCAPS
wMid As Integer
wPid As Integer
vDriverVersion As Long
szPname As String * MAXPNAMELEN
wTechnology As Integer
dwSupport As Long
End Type
Private Type VolumeSetting
LeftVol As Integer
RightVol As Integer
End Type
Private Declare Function auxGetNumDevs Lib "winmm.dll" () As Long
Private Declare Function auxGetDevCaps Lib "winmm.dll" Alias "auxGetDevCapsA" (ByVal uDeviceID As Long, lpCaps As AUXCAPS, ByVal uSize As Long) As Long
Private Declare Function auxSetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, ByVal dwVolume As Long) As Long
Private Declare Function auxGetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, ByRef lpdwVolume As VolumeSetting) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Function nSigned(ByVal lUnsignedInt As Long) As Integer
Dim nReturnVal As Integer ' Return value from Function
If lUnsignedInt > 65535 Or lUnsignedInt < 0 Then
MsgBox "Error in conversion from Unsigned to nSigned Integer"
nSignedInt = 0
Exit Function
End If
If lUnsignedInt > 32767 Then
nReturnVal = lUnsignedInt - 65536
Else
nReturnVal = lUnsignedInt
End If
nSigned = nReturnVal
End Function
Private Function lUnsigned(ByVal nSignedInt As Integer) As Long
Dim lReturnVal As Long ' Return value from Function
If nSignedInt < 0 Then
lReturnVal = nSignedInt + 65536
Else
lReturnVal = nSignedInt
End If
If lReturnVal > 65535 Or lReturnVal < 0 Then
MsgBox "Error in conversion from nSigned to Unsigned Integer"
lReturnVal = 0
End If
lUnsigned = lReturnVal
End Function
Private Function lSetVolume(ByRef lLeftVol As Long, ByRef lRightVol As Long, lDeviceID As Long) As Long
Dim Volume As VolumeSetting, lBothVolumes As Long
Volume.LeftVol = nSigned(lLeftVol * 65535 / HIGHEST_VOLUME_SETTING)
Volume.RightVol = nSigned(lRightVol * 65535 / HIGHEST_VOLUME_SETTING)
'copy our Volume-variable to a long
CopyMemory lBothVolumes, Volume.LeftVol, Len(Volume)
'call the SetVolume-function
lSetVolume = auxSetVolume(lDeviceID, lBothVolumes)
End Function
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim Volume As VolumeSetting, Cnt As Long, AC As AUXCAPS
'set the output to a persistent graphic
Me.AutoRedraw = True
'loop through all the devices
For Cnt = 0 To auxGetNumDevs - 1 'auxGetNumDevs is zero-based
'get the volume
auxGetVolume Cnt, Volume
'get the device capabilities
auxGetDevCaps Cnt, AC, Len(AC)
'print the name on the form
Me.Print "Device #" + Str$(Cnt + 1) + ": " + Left(AC.szPname, InStr(AC.szPname, vbNullChar) - 1)
'print the left- and right volume on the form
Me.Print "Left volume:" + Str$(HIGHEST_VOLUME_SETTING * lUnsigned(Volume.LeftVol) / 65535)
Me.Print "Right volume:" + Str$(HIGHEST_VOLUME_SETTING * lUnsigned(Volume.RightVol) / 65535)
'set the left- and right-volume to 50%
lSetVolume 50, 50, Cnt
Me.Print "Both volumes now set to 50%"
'empty line
Me.Print
Next
End Sub
我不相信有一种简单的方法可以在 XP 下获得当前的峰值。MIXERCONTROL_CONTROLTYPE_PEAKMETER 存在,但我相信它在很大程度上不受支持(它在我当前的机器上)。我猜您将创建自己的分析当前音频输出的方法,请查看此处的 DSP 部分。
您可以在运行时决定要使用哪种方法,XP 和 Vista/7 处理音频的方法非常不同。我之前写的关于这个问题的一些可能有用的信息可以在这里。
在我看来,MSDN 文档和 Larry Osterman 的(他也是 SO 的成员)博客可能是当前 Windows 音频基础设施的 2 个最有用的资源。
从代码项目中查看此代码:使用 DirectX 的 LED 样式音量计
本文作为我创建的名为 AnalogSignalMeter 的 UserControl 的使用手册。此控件使用 Direct3D 绘制控件,并使用 DirectSound 对音频信号进行采样。
它有一个 AnalogSignalMeter 对象,该对象会触发一个事件,该事件将报告当前的左右扬声器电平。