Cambiar el nivel de volumen maestro
Pregunta
¿Cómo puedo cambiar el nivel de volumen maestro? Usando este código
[DllImport ("winmm.dll")]
public static extern int waveOutSetVolume (IntPtr hwo, uint dwVolume);
waveOutSetVolume (IntPtr.Zero, (((uint)uint.MaxValue & 0x0000ffff) | ((uint)uint.MaxValue << 16)));
Puedo configurar el volumen de la onda, pero si el volumen maestro es demasiado bajo, esto no tendrá ningún efecto.
Gracias por cualquier ayuda.
Solución
Bien, aquí va:
const int MAXPNAMELEN = 32;
const int MIXER_SHORT_NAME_CHARS = 16;
const int MIXER_LONG_NAME_CHARS = 64;
[Flags] enum MIXERLINE_LINEF : uint{
ACTIVE = 0x00000001,
DISCONNECTED = 0x00008000,
SOURCE = 0x80000000
}
[Flags] enum MIXER : uint{
GETLINEINFOF_DESTINATION = 0x00000000,
GETLINEINFOF_SOURCE = 0x00000001,
GETLINEINFOF_LINEID = 0x00000002,
GETLINEINFOF_COMPONENTTYPE = 0x00000003,
GETLINEINFOF_TARGETTYPE = 0x00000004,
GETLINEINFOF_QUERYMASK = 0x0000000F,
GETLINECONTROLSF_ALL = 0x00000000,
GETLINECONTROLSF_ONEBYID = 0x00000001,
GETLINECONTROLSF_ONEBYTYPE = 0x00000002,
GETLINECONTROLSF_QUERYMASK = 0x0000000F,
GETCONTROLDETAILSF_VALUE = 0x00000000,
GETCONTROLDETAILSF_LISTTEXT = 0x00000001,
GETCONTROLDETAILSF_QUERYMASK = 0x0000000F,
OBJECTF_MIXER = 0x00000000,
OBJECTF_WAVEOUT = 0x10000000,
OBJECTF_WAVEIN = 0x20000000,
OBJECTF_MIDIOUT = 0x30000000,
OBJECTF_MIDIIN = 0x40000000,
OBJECTF_AUX = 0x50000000,
OBJECTF_HANDLE = 0x80000000,
OBJECTF_HMIXER = OBJECTF_HANDLE | OBJECTF_MIXER,
OBJECTF_HWAVEOUT = OBJECTF_HANDLE | OBJECTF_WAVEOUT,
OBJECTF_HWAVEIN = OBJECTF_HANDLE | OBJECTF_WAVEIN,
OBJECTF_HMIDIOUT = OBJECTF_HANDLE | OBJECTF_MIDIOUT,
OBJECTF_HMIDIIN = OBJECTF_HANDLE | OBJECTF_MIDIIN
}
[Flags] enum MIXERCONTROL_CT : uint{
CLASS_MASK = 0xF0000000,
CLASS_CUSTOM = 0x00000000,
CLASS_METER = 0x10000000,
CLASS_SWITCH = 0x20000000,
CLASS_NUMBER = 0x30000000,
CLASS_SLIDER = 0x40000000,
CLASS_FADER = 0x50000000,
CLASS_TIME = 0x60000000,
CLASS_LIST = 0x70000000,
SUBCLASS_MASK = 0x0F000000,
SC_SWITCH_BOOLEAN = 0x00000000,
SC_SWITCH_BUTTON = 0x01000000,
SC_METER_POLLED = 0x00000000,
SC_TIME_MICROSECS = 0x00000000,
SC_TIME_MILLISECS = 0x01000000,
SC_LIST_SINGLE = 0x00000000,
SC_LIST_MULTIPLE = 0x01000000,
UNITS_MASK = 0x00FF0000,
UNITS_CUSTOM = 0x00000000,
UNITS_BOOLEAN = 0x00010000,
UNITS_SIGNED = 0x00020000,
UNITS_UNSIGNED = 0x00030000,
UNITS_DECIBELS = 0x00040000, /* in 10ths */
UNITS_PERCENT = 0x00050000, /* in 10ths */
}
[Flags] enum MIXERCONTROL_CONTROLTYPE : uint{
CUSTOM = MIXERCONTROL_CT.CLASS_CUSTOM | MIXERCONTROL_CT.UNITS_CUSTOM,
BOOLEANMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_BOOLEAN,
SIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_SIGNED,
PEAKMETER = SIGNEDMETER + 1,
UNSIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_UNSIGNED,
BOOLEAN = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BOOLEAN | MIXERCONTROL_CT.UNITS_BOOLEAN,
ONOFF = BOOLEAN + 1,
MUTE = BOOLEAN + 2,
MONO = BOOLEAN + 3,
LOUDNESS = BOOLEAN + 4,
STEREOENH = BOOLEAN + 5,
BASS_BOOST = BOOLEAN + 0x00002277,
BUTTON = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BUTTON | MIXERCONTROL_CT.UNITS_BOOLEAN,
DECIBELS = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_DECIBELS,
SIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_SIGNED,
UNSIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_UNSIGNED,
PERCENT = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_PERCENT,
SLIDER = MIXERCONTROL_CT.CLASS_SLIDER | MIXERCONTROL_CT.UNITS_SIGNED,
PAN = SLIDER + 1,
QSOUNDPAN = SLIDER + 2,
FADER = MIXERCONTROL_CT.CLASS_FADER | MIXERCONTROL_CT.UNITS_UNSIGNED,
VOLUME = FADER + 1,
BASS = FADER + 2,
TREBLE = FADER + 3,
EQUALIZER = FADER + 4,
SINGLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_SINGLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
MUX = SINGLESELECT + 1,
MULTIPLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_MULTIPLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
MIXER = MULTIPLESELECT + 1,
MICROTIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MICROSECS | MIXERCONTROL_CT.UNITS_UNSIGNED,
MILLITIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MILLISECS | MIXERCONTROL_CT.UNITS_UNSIGNED
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct MIXERLINE{
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct TargetInfo{
public uint dwType;
public uint dwDeviceID;
public ushort wMid;
public ushort wPid;
public uint vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAXPNAMELEN)]
public string szPname;
}
public uint cbStruct;
public uint dwDestination;
public uint dwSource;
public uint dwLineID;
public MIXERLINE_LINEF fdwLine;
public uint dwUser;
public uint dwComponentType;
public uint cChannels;
public uint cConnection;
public uint cControls;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_SHORT_NAME_CHARS)]
public string szShortName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_LONG_NAME_CHARS)]
public string szName;
public TargetInfo Target;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct MIXERCONTROL{
[StructLayout(LayoutKind.Explicit)]
public struct BoundsInfo{
[FieldOffset(0)]
public int lMinimum;
[FieldOffset(4)]
public int lMaximum;
[FieldOffset(0)]
public uint dwMinimum;
[FieldOffset(4)]
public uint dwMaximum;
[FieldOffset(8), MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public uint[] dwReserved;
}
[StructLayout(LayoutKind.Explicit)]
public struct MetricsInfo{
[FieldOffset(0)]
public uint cSteps;
[FieldOffset(0)]
public uint cbCustomData;
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst=5)]
public uint[] dwReserved;
}
public uint cbStruct;
public uint dwControlID;
public MIXERCONTROL_CONTROLTYPE dwControlType;
public uint fdwControl;
public uint cMultipleItems;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_SHORT_NAME_CHARS)]
public string szShortName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_LONG_NAME_CHARS)]
public string szName;
public BoundsInfo Bounds;
public MetricsInfo Metrics;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERLINECONTROLS{
[FieldOffset(0)]
public uint cbStruct;
[FieldOffset(4)]
public uint dwLineID;
[FieldOffset(8)]
public uint dwControlID;
[FieldOffset(8)] // not a typo! overlaps previous field
public uint dwControlType;
[FieldOffset(12)]
public uint cControls;
[FieldOffset(16)]
public uint cbmxctrl;
[FieldOffset(20)]
public IntPtr pamxctrl;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERCONTROLDETAILS{
[FieldOffset(0)]
public uint cbStruct;
[FieldOffset(4)]
public uint dwControlID;
[FieldOffset(8)]
public uint cChannels;
[FieldOffset(12)]
public IntPtr hwndOwner;
[FieldOffset(12)] // not a typo!
public uint cMultipleItems;
[FieldOffset(16)]
public uint cbDetails;
[FieldOffset(20)]
public IntPtr paDetails;
}
[StructLayout(LayoutKind.Sequential)]
struct VOLUME{
public int left;
public int right;
}
struct MixerInfo{
public uint volumeCtl;
public uint muteCtl;
public int minVolume;
public int maxVolume;
}
[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetLineInfo (IntPtr hmxobj, ref MIXERLINE pmxl, MIXER flags);
[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetLineControls (IntPtr hmxobj, ref MIXERLINECONTROLS pmxlc, MIXER flags);
[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);
[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerSetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);
static MixerInfo GetMixerControls(){
MIXERLINE mxl = new MIXERLINE();
MIXERLINECONTROLS mlc = new MIXERLINECONTROLS();
mxl.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINE));
mlc.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINECONTROLS));
mixerGetLineInfo(IntPtr.Zero, ref mxl, MIXER.OBJECTF_MIXER | MIXER.GETLINEINFOF_DESTINATION);
mlc.dwLineID = mxl.dwLineID;
mlc.cControls = mxl.cControls;
mlc.cbmxctrl = (uint)Marshal.SizeOf(typeof(MIXERCONTROL));
mlc.pamxctrl = Marshal.AllocHGlobal((int)(mlc.cbmxctrl * mlc.cControls));
mixerGetLineControls(IntPtr.Zero, ref mlc, MIXER.OBJECTF_MIXER | MIXER.GETLINECONTROLSF_ALL);
MixerInfo rtn = new MixerInfo();
for(int i = 0; i < mlc.cControls; i++){
MIXERCONTROL mxc = (MIXERCONTROL)Marshal.PtrToStructure((IntPtr)((int)mlc.pamxctrl + (int)mlc.cbmxctrl * i), typeof(MIXERCONTROL));
switch(mxc.dwControlType){
case MIXERCONTROL_CONTROLTYPE.VOLUME:
rtn.volumeCtl = mxc.dwControlID;
rtn.minVolume = mxc.Bounds.lMinimum;
rtn.maxVolume = mxc.Bounds.lMaximum;
break;
case MIXERCONTROL_CONTROLTYPE.MUTE:
rtn.muteCtl = mxc.dwControlID;
break;
}
}
Marshal.FreeHGlobal(mlc.pamxctrl);
return rtn;
}
static VOLUME GetVolume(MixerInfo mi){
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.volumeCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 2;
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(int));
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);
mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);
VOLUME rtn = (VOLUME)Marshal.PtrToStructure(mcd.paDetails, typeof(VOLUME));
Marshal.FreeHGlobal(mcd.paDetails);
return rtn;
}
static bool IsMuted(MixerInfo mi){
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.muteCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 1;
mcd.cbDetails = 4;
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);
mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);
int rtn = Marshal.ReadInt32(mcd.paDetails);
Marshal.FreeHGlobal(mcd.paDetails);
return rtn != 0;
}
static void AdjustVolume(MixerInfo mi, int delta){
VOLUME volume = GetVolume(mi);
if(delta > 0){
volume.left = Math.Min(mi.maxVolume, volume.left + delta);
volume.right = Math.Min(mi.maxVolume, volume.right + delta);
}else{
volume.left = Math.Max(mi.minVolume, volume.left + delta);
volume.right = Math.Max(mi.minVolume, volume.right + delta);
}
SetVolume(mi, volume);
}
static void SetVolume(MixerInfo mi, VOLUME volume){
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.volumeCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 2;
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(int));
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);
Marshal.StructureToPtr(volume, mcd.paDetails, false);
mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);
Marshal.FreeHGlobal(mcd.paDetails);
}
static void SetMute(MixerInfo mi, bool mute){
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
mcd.dwControlID = mi.muteCtl;
mcd.cMultipleItems = 0;
mcd.cChannels = 1;
mcd.cbDetails = 4;
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);
Marshal.WriteInt32(mcd.paDetails, mute ? 1 : 0);
mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);
Marshal.FreeHGlobal(mcd.paDetails);
}
Este código es enorme y feo. Es una traducción de algún código de C ++, y al tener que definir todas las cosas de P / Invoke, es mucho más código. Pero lo probé y funciona. Para usarlo, simplemente necesita algo como:
MixerInfo mi = GetMixerControls();
AdjustVolume(mi, 100); // add 100 to the current volume
o
MixerInfo mi = GetMixerControls();
AdjustVolume(mi, (mi.maxVolume - mi.minVolume) / 10); // increase the volume by 10% of total range
o
MixerInfo mi = GetMixerControls();
SetVolume(mi, mi.maxVolume); // let's get this party crunk'd!
o
MixerInfo mi = GetMixerControls();
SetMute(mi, true); // shhhh!!!!!!
ADVERTENCIA
Debido al uso de entradas de tamaño fijo y compensaciones de campo, esto puede fallar fantásticamente en Windows de 64 bits. No sé, no lo he probado y no he prestado suficiente atención para saber si estos tamaños de campo se expanden a 64 bits. advertencia codor
EDIT
En aras de la simplicidad (relativamente hablando), he dejado de lado cualquier manejo de errores. Realmente deberías verificar los códigos de retorno de todas las funciones de mixerXXX, pero lo dejaré como un ejercicio para el lector (léase como: era demasiado vago para hacer esto).
Otros consejos
Para el volumen maestro (para Vista y superior), eso sería:
ISimpleAudioVolume :: SetMasterVolume
Como se explica aquí , puede consultar la sección:
Core Audio APIs en Windows Vista para obtener más información.
Esta llamada no es una llamada de Media Foundation sino una llamada WASAPI (Windows Audio Session API): ISimpleAudioVolume :: SetMasterVolume (El método SetMasterVolume establece el nivel de volumen maestro para la sesión de audio).
Sin embargo, esto puede ser difícil de hacer que la interfaz de usuario del Media Center refleje el nuevo nivel de sonido establecido por esa llamada, ya que esto el hilo lo ilustra .
Para Windows Xp, puede estudiar este script y tal vez este otro script .
Biblioteca de audio también podría ser de interés.
También existe este viejo Proyecto de audio que tiene parte del volumen maestro:
BOOL CVolumeDlg::amdInitialize()
{
ASSERT(m_hMixer == NULL);
// get the number of mixer devices present in the system
m_nNumMixers = ::mixerGetNumDevs();
m_hMixer = NULL;
::ZeroMemory(&m_mxcaps, sizeof(MIXERCAPS));
m_strDstLineName.Empty();
m_strVolumeControlName.Empty();
m_dwMinimum = 0;
m_dwMaximum = 0;
m_dwVolumeControlID = 0;
// open the first mixer
// A "mapper" for audio mixer devices does not currently exist.
if (m_nNumMixers != 0)
{
if (::mixerOpen(&m_hMixer,
0,
reinterpret_cast<DWORD>(this->GetSafeHwnd()),
NULL,
MIXER_OBJECTF_MIXER | CALLBACK_WINDOW)
!= MMSYSERR_NOERROR)
{
return FALSE;
}
if (::mixerGetDevCaps(reinterpret_cast<UINT>(m_hMixer),
&m_mxcaps, sizeof(MIXERCAPS))
!= MMSYSERR_NOERROR)
{
return FALSE;
}
}
return TRUE;
}
BOOL CVolumeDlg::amdUninitialize()
{
BOOL bSucc = TRUE;
if (m_hMixer != NULL)
{
bSucc = (::mixerClose(m_hMixer) == MMSYSERR_NOERROR);
m_hMixer = NULL;
}
return bSucc;
}
BOOL CVolumeDlg::amdGetMasterVolumeControl()
{
if (m_hMixer == NULL)
{
return FALSE;
}
// get dwLineID
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if (::mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(m_hMixer),
&mxl,
MIXER_OBJECTF_HMIXER |
MIXER_GETLINEINFOF_COMPONENTTYPE)
!= MMSYSERR_NOERROR)
{
return FALSE;
}
// get dwControlID
MIXERCONTROL mxc;
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = &mxc;
if (::mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(m_hMixer),
&mxlc,
MIXER_OBJECTF_HMIXER |
MIXER_GETLINECONTROLSF_ONEBYTYPE)
!= MMSYSERR_NOERROR)
{
return FALSE;
}
// store dwControlID
m_strDstLineName = mxl.szName;
m_strVolumeControlName = mxc.szName;
m_dwMinimum = mxc.Bounds.dwMinimum;
m_dwMaximum = mxc.Bounds.dwMaximum;
m_dwVolumeControlID = mxc.dwControlID;
return TRUE;
}
BOOL CVolumeDlg::amdGetMasterVolumeValue(DWORD &dwVal) const
{
if (m_hMixer == NULL)
{
return FALSE;
}
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwVolumeControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
if (::mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(m_hMixer),
&mxcd,
MIXER_OBJECTF_HMIXER |
MIXER_GETCONTROLDETAILSF_VALUE)
!= MMSYSERR_NOERROR)
{
return FALSE;
}
dwVal = mxcdVolume.dwValue;
return TRUE;
}
BOOL CVolumeDlg::amdSetMasterVolumeValue(DWORD dwVal) const
{
if (m_hMixer == NULL)
{
return FALSE;
}
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = { dwVal };
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = m_dwVolumeControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
if (::mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(m_hMixer),
&mxcd,
MIXER_OBJECTF_HMIXER |
MIXER_SETCONTROLDETAILSF_VALUE)
!= MMSYSERR_NOERROR)
{
return FALSE;
}
return TRUE;
}
Use esta biblioteca gratuita, es simple y hace el trabajo. InputSimulator
Simula presionar una tecla. Solo tiene que agregar esta referencia y llamar a donde quiera métodos estáticos como estos:
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_UP);
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_DOWN);
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_MUTE);
Luego, si desea obtener el nivel de vokume maestro, haga lo siguiente:
// volume update
MMDevice defaultDevice = new MMDeviceEnumerator()
.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
// veloce attesa per l'aggiornamento del volume
Thread.Sleep(100);
float level = defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar;
Al hacer esto, tendrá el nivel del volumen actual en formato 0-1 (por ejemplo, el 52% es 0.52) Si desea tenerlo en formato 0-100, simplemente haga el nivel * 100