Получить мастер громкости звука в C#
Мне нужно получить текущую громкость звука на звуковой карте.
Есть идеи как?
8 ответов
Вы можете получить эти значения, используя IAudioMeterInformation в API-интерфейсах CoreAudio в Vista и Win 7.
Управляемые обертки доступны в NAudio (получить по AudioMeterInformation от MMDevice).
static int PlayerVolume()
{
RecordPlayer rp = new RecordPlayer();
rp.PlayerID = -1;
int playerVolume = rp.PlayerVolume;
return playerVolume;
}
из модифицированной громкости микрофона в статье C#
Я решил это, когда работал над (еще не выпущенным...) приложением, которое запускает какую-то "музыку лифта", когда нет другого звука.
Следуя блестящим советам, данным Марком Хитом, я получил то, что хотел:
using NAudio.CoreAudioApi;
MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
string currVolume = "MasterPeakVolume : " + defaultDevice.AudioMeterInformation.MasterPeakValue.ToString();
Может быть, 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
Посмотрите в MSDN информацию для:
- IMMDeviceCollection, IMMDevice и IAudioEndpointVolume (только Windows Vista, Windows 7).
- mixerGetNumDevs, mixerGetLineControls,...
Это "общая" информация. Возможно, у C# есть более удобные способы (я не знаю).
Я не верю, что есть простой способ получить текущий Пик под XP. MIXERCONTROL_CONTROLTYPE_PEAKMETER присутствует, но я считаю, что он в основном не поддерживается (он на моем текущем компьютере). Я предполагаю, что вам придется создать свой собственный метод анализа текущего аудио выхода, посмотрите здесь раздел DSP.
Вы можете просто решить во время выполнения, какой метод вы хотели бы использовать, XP и Vista/7 имеют совершенно разные методы работы со звуком. Некоторая, возможно, полезная информация по этому вопросу, которую я написал ранее, может быть здесь.
Документация MSDN и блог Ларри Остермана (он также является членом SO), возможно, являются, по моему мнению, 2 наиболее полезными источниками для текущей звуковой инфраструктуры Windows.
Проверьте этот код из Code Project: светодиодный измеритель громкости с использованием DirectX
Эта статья служит руководством по использованию для UserControl, который я создал под названием AnalogSignalMeter. Этот элемент управления использует Direct3D для рисования элемента управления и DirectSound для выборки аудиосигнала.
У него есть объект AnalogSignalMeter, который вызывает событие, сообщающее о текущем уровне левого и правого динамика.
Я очень старался и в конце концов добился успеха, эти « VtblGaps » - ключ! ... Просто скопируйте и вставьте в новый скрипт C#:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MMDeviceAPI
{
public class MMDeviceController
{
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
private class MMDeviceEnumerator
{
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IMMDeviceEnumerator
{
void _VtblGap1_1();
//void _VtblGap1_5(); /// (Alternative)
[PreserveSig]
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IMMDevice
{
[PreserveSig]
int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
void _VtblGap1_1();
int GetId([MarshalAs(UnmanagedType.LPWStr)] out string strId);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IAudioEndpointVolume
{
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IGetChannelCount : IAudioEndpointVolume
{
void _VtblGap1_2();
int GetChannelCount(ref uint pnChannelCount);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IGetChannelVolumeLevelScalar : IAudioEndpointVolume
{
void _VtblGap1_10();
int GetChannelVolumeLevelScalar(uint nChannel, ref float pfLevel);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IGetMasterVolumeLevelScalar : IAudioEndpointVolume
{
void _VtblGap1_6();
int GetMasterVolumeLevelScalar(ref float pfLevel);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IGetMute : IAudioEndpointVolume
{
void _VtblGap1_12();
int GetMute([MarshalAs(UnmanagedType.Bool)] ref bool pbMute);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ISetChannelVolumeLevelScalar : IAudioEndpointVolume
{
void _VtblGap1_8();
int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ISetMasterVolumeLevelScalar : IAudioEndpointVolume
{
void _VtblGap1_4();
int SetMasterVolumeLevelScalar(float fLevel, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ISetMute : IAudioEndpointVolume
{
void _VtblGap1_11();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);
}
public enum EDataFlow { eRender, eCapture, eAll };
public enum ERole { eConsole, eMultimedia, eCommunications };
///====================================================================================================
private static IAudioEndpointVolume GetMMDeviceAudioEndpointVolume(EDataFlow dataFlow, ERole role)
{
IMMDeviceEnumerator MMDeviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
MMDeviceEnumerator.GetDefaultAudioEndpoint(dataFlow, role, out IMMDevice MMDevice);
MMDevice.Activate(typeof(IAudioEndpointVolume).GUID, 0, IntPtr.Zero, out object o);
IAudioEndpointVolume AudioEndpointVolume = (IAudioEndpointVolume)o;
Marshal.ReleaseComObject(MMDevice);
Marshal.ReleaseComObject(MMDeviceEnumerator);
return AudioEndpointVolume;
}
public static uint GetChannelCount(EDataFlow dataFlow, ERole role)
{
IGetChannelCount AudioEndpointVolume = (IGetChannelCount)GetMMDeviceAudioEndpointVolume(dataFlow, role);
uint returnValue = 0;
AudioEndpointVolume.GetChannelCount(ref returnValue);
Marshal.ReleaseComObject(AudioEndpointVolume);
return returnValue;
}
public static float GetChannelVolumeLevelScalar(EDataFlow dataFlow, ERole role, uint channel)
{
IGetChannelVolumeLevelScalar AudioEndpointVolume = (IGetChannelVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);
float returnValue = 0;
AudioEndpointVolume.GetChannelVolumeLevelScalar(channel, ref returnValue);
Marshal.ReleaseComObject(AudioEndpointVolume);
return returnValue;
}
public static float GetMasterVolumeLevelScalar(EDataFlow dataFlow, ERole role)
{
IGetMasterVolumeLevelScalar AudioEndpointVolume = (IGetMasterVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);
float returnValue = 0f;
AudioEndpointVolume.GetMasterVolumeLevelScalar(ref returnValue);
Marshal.ReleaseComObject(AudioEndpointVolume);
return returnValue;
}
public static bool GetMute(EDataFlow dataFlow, ERole role)
{
IGetMute AudioEndpointVolume = (IGetMute)GetMMDeviceAudioEndpointVolume(dataFlow, role);
bool returnValue = false;
AudioEndpointVolume.GetMute(ref returnValue);
Marshal.ReleaseComObject(AudioEndpointVolume);
return returnValue;
}
public static void SetChannelVolumeLevelScalar(EDataFlow dataFlow, ERole role, uint channel, float volume)
{
ISetChannelVolumeLevelScalar AudioEndpointVolume = (ISetChannelVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);
AudioEndpointVolume.SetChannelVolumeLevelScalar(channel, volume, Guid.Empty);
Marshal.ReleaseComObject(AudioEndpointVolume);
}
public static void SetMasterVolumeLevelScalar(EDataFlow dataFlow, ERole role, float volume)
{
ISetMasterVolumeLevelScalar AudioEndpointVolume = (ISetMasterVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);
AudioEndpointVolume.SetMasterVolumeLevelScalar(volume, Guid.Empty);
Marshal.ReleaseComObject(AudioEndpointVolume);
}
public static void SetMute(EDataFlow dataFlow, ERole role, bool mute)
{
ISetMute AudioEndpointVolume = (ISetMute)GetMMDeviceAudioEndpointVolume(dataFlow, role);
AudioEndpointVolume.SetMute(mute, Guid.Empty);
Marshal.ReleaseComObject(AudioEndpointVolume);
}
///====================================================================================================
public static void TestFunctionality()
{
int device = 0;
EDataFlow dataFlow;
ERole eRole;
while (true)
{
device++;
switch (device)
{
case 1:
dataFlow = EDataFlow.eRender;
eRole = ERole.eMultimedia;
break;
case 2:
dataFlow = EDataFlow.eCapture;
eRole = ERole.eMultimedia;
break;
default:
return;
}
MessageBox.Show($"[EDataFlow & ERole]: {dataFlow.ToString()}_{eRole.ToString()}");
uint channels = GetChannelCount(dataFlow, eRole); MessageBox.Show("[GetChannelCount]: " + channels);
MessageBox.Show("[GetChannelVolumeLevelScalar #0]: " + GetChannelVolumeLevelScalar(dataFlow, eRole, 0).ToString());
if (channels > 1) { MessageBox.Show("[GetChannelVolumeLevelScalar #1]: " + GetChannelVolumeLevelScalar(dataFlow, eRole, 1).ToString()); }
MessageBox.Show("[GetMasterVolumeLevelScalar]: " + GetMasterVolumeLevelScalar(dataFlow, eRole).ToString());
MessageBox.Show("[GetMute]: " + GetMute(dataFlow, eRole).ToString());
MessageBox.Show("[SetChannelVolumeLevelScalar #0]: 0.44"); SetChannelVolumeLevelScalar(dataFlow, eRole, 0, 0.44f);
if (channels > 1) { MessageBox.Show("[SetChannelVolumeLevelScalar #1]: 0.88"); SetChannelVolumeLevelScalar(dataFlow, eRole, 1, 0.88f); }
MessageBox.Show("[SetMasterVolumeLevelScalar]: 0.55"); SetMasterVolumeLevelScalar(dataFlow, eRole, 0.55f);
MessageBox.Show("[SetMute]: false"); SetMute(dataFlow, eRole, false);
}
}
///====================================================================================================
}
}