在c#中获取主音量

21

我需要获取当前输出到声卡的音量。

有什么想法吗?


另一种解决方案是来自Code Project的这篇文章:VolumeMeter(Managed DirectX) - loraderon
你想要当前音量还是当前最大音量?如果你想要当前最大音量,这在Vista+和XP上显然是“不同”的,请参见https://dev59.com/4lPTa4cB1Zd3GeqPhT37。 - rogerdpack
7个回答

13

你可以使用Vista和Win 7中的CoreAudio APIs中的IAudioMeterInformation获取这些值。

NAudio中提供了托管包装器(从MMDevice获取AudioMeterInformation)。


4

我曾在一款(尚未发布的...)应用程序中解决了这个问题,该应用程序在没有其他声音时会播放某种“电梯音乐”。

在遵循Mark Heath提供的妙招后,我终于得到了想要的效果:

 using NAudio.CoreAudioApi; 
 MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
 MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
 string currVolume = "MasterPeakVolume : " + defaultDevice.AudioMeterInformation.MasterPeakValue.ToString();

1
成功了!谢谢!(需要从Nuget添加NAudio) - Mayer Spitz

4
    static int PlayerVolume()
    {
        RecordPlayer rp = new RecordPlayer();
        rp.PlayerID = -1;
        int playerVolume = rp.PlayerVolume;
        return playerVolume;
    }

来自修改后的C#中的麦克风音量文章


2

请查看MSDN文档,寻找以下内容:

  • IMMDeviceCollection、IMMDevice和IAudioEndpointVolume(仅适用于Windows Vista、Windows 7)。
  • mixerGetNumDevs、mixerGetLineControls等。

这是“常见”的信息。可能C#有更方便的方法(我不知道)。


他正在要求主通道实际实时音频输出音量测量,而不是设置混音器旋钮的句柄。你看到他在截图上选择的那部分了吗?据我所知,这些Win API并没有提供访问该“实时”信息的权限。 - Mike Atlas
1
Mike Atlas,你是对的。在这种情况下应该使用IAudioMeterInformation(正如Mark Heath所指出的)。 - VitalyVal

2

也许 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

或者可能是这个: http://blackbeltvb.com/index.htm?free/mcisamp.htm


那看起来像是设置音量,我认为他们在问当前的音频输出,或者说从扬声器中当前发出的声音有多大声。 - GalacticJello
哦,我明白他在问音频音量值:auxGetVolume似乎提供了这个信息。那么,auxGetDevCaps也许可以帮助确定当前的输出设备? - JoeBilly

1

我不相信在XP下有一种简单的方法来获取当前峰值。MIXERCONTROL_CONTROLTYPE_PEAKMETER存在,但我认为它在很大程度上得不到支持(它在我的当前机器上)。我猜想你将不得不创建自己的方法来分析当前音频输出,请查看DSP部分这里

您可以在运行时决定要使用哪种方法,XP和Vista/7处理音频的方法非常不同。我之前写过一些关于此事的可能有用的信息在这里

在我看来,MSDN文档和Larry Osterman(他也是SO的成员)的博客可能是当前Windows音频基础设施最有用的两个来源。


0

看看Code Project上的这段代码:使用DirectX的LED风格音量计

本文是我创建的一个名为AnalogSignalMeter的用户控件的用法手册。该控件使用Direct3D来绘制控件, 使用DirectSound来采样音频信号。

它有一个AnalogSignalMeter对象,触发一个事件,将报告当前左右扬声器的级别。


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