views:

1121

answers:

6

Hi, I need to get the current volume of what that outs to the sound card, for example, this value:

alt text

Any ideas how?

Thank you.

+2  A: 

Look in MSDN information for:

  • IMMDeviceCollection, IMMDevice and IAudioEndpointVolume (only Windows Vista, Windows 7).
  • mixerGetNumDevs, mixerGetLineControls,...

This is "common" information. It is possible C# has more convenient ways (I do not know).

VitalyVal
He's asking for the actual real-time audio output volume measurement on the Master channel, not a handle to set the mixer dial. See the part that he selected on the screenshot? As far as I can tell, those Win APIs don't offer access to that "realtime" information.
Mike Atlas
Mike Atlas, you are right. In this case IAudioMeterInformation should be used (as pointed by Mark Heath).
VitalyVal
+7  A: 

You can get at these values using IAudioMeterInformation in the CoreAudio APIs in Vista and Win 7.

Managed wrappers are available in NAudio (get at the AudioMeterInformation from the MMDevice).

Mark Heath
I'm looking for a solution that will work in XP either..
TTT
A: 

Check out this code from Code Project: LED Style Volume Meter Using DirectX

This article serves as a usage manual for a UserControl I created called AnalogSignalMeter. This control uses Direct3D to paint the control, and DirectSound to sample the audio signal.

It has an AnalogSignalMeter object, that is fired an event which will report the current left and right speaker level.

GalacticJello
A: 

I don't believe there is an easy way to get the current Peak under XP. MIXERCONTROL_CONTROLTYPE_PEAKMETER is present but I believe it is largely unsupported (it is on my current machine). I am guessing you will have create your own method of analysing the current audio output, have a look at the DSP section here.

You can just decide at runtime which method you would like to use, XP and Vista/7 have very different methods of dealing with the audio. Some possibly useful information on this matter I wrote previously can be here.

The MSDN documentation and Larry Osterman's (he is also a member on SO) blog are probably the 2 most useful sources for current windows audio infrastructure in my opinion.

YoungPony
A: 

Maybe the winmm.dll can help you :

From 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: [email protected]
    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

Or maybe this : http://blackbeltvb.com/index.htm?free/mcisamp.htm

JoeBilly
That looks like it sets the volume, I think they are asking for the current audio output, or how loud the sound is that is currently emiting from the speakers.
GalacticJello
Oh I understood he asking for the audio volume value : the auxGetVolume seams to provide this information.So maybe the auxGetDevCaps may help about the current output device ?
JoeBilly
A: 

Working on an application that initiates some kind of "elevator music" when no other sound is present, working with the tips given by Mark Heath, I got what I wanted :

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