Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Getting and Setting Windows System Audio Volume

5.00/5 (2 votes)
4 Apr 2023CPOL 7.4K  
Demonstrates two functions to retrieve the current Windows System Audio Volume and set Audio Volume.
Get or Set the Windows System audio volume with a simple method call.

Introduction

Currently, there are no .NET classes that provide methods to retrieve or set the system output volume. Using interfaces to the Windows Multi-Media Device APIs, this article provides a solution.

Background

I got the idea for this article from this web page. I refined it a bit so that it can be dropped into your VB .NET or C# source code and used immediately.

Using the Code

To retrieve the current system audio volume setting value as an integer (0 - 100), call the GetVolume() function.

VB.NET
Dim currentVolume As Integer = GetVolume()
C#
int currentVolume = SystemAudio.WindowsSystemAudio.GetVolume();

To set the current system audio volume setting to a new value (0 - 100), call the SetVolume() function.

VB.NET
SetVolume(30)
C#
SystemAudio.WindowsSystemAudio.SetVolume(30);

The following is the source code for the VB.NET and C# methods that call the Windows Multi-Media APIs to either get or set the Windows System audio volume.

VB.NET
Option Strict Off
Imports System
Imports System.Runtime.InteropServices

Module WindowsSystemAudio
    <ComImport>
    <Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), _
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Private Interface IMMDeviceEnumerator
#Disable Warning IDE1006 ' Naming Styles
        Sub lpVtbl()
#Enable Warning IDE1006 ' Naming Styles
        Function GetDefaultAudioEndpoint(ByVal dataFlow As Integer, _
        ByVal role As Integer, <Out> ByRef ppDevice As IMMDevice) As Integer
    End Interface

    Private NotInheritable Class MMDeviceEnumeratorFactory
        Public Shared Function CreateInstance() As IMMDeviceEnumerator
            Return CType(Activator.CreateInstance_
            (Type.GetTypeFromCLSID(New Guid_
            ("BCDE0395-E52F-467C-8E3D-C4579291692E"))), _
            IMMDeviceEnumerator) ' a MMDeviceEnumerator
        End Function
    End Class

    <Guid("D666063F-1587-4E43-81F1-B948E807363F"), _
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Private Interface IMMDevice
        Function Activate(
    <MarshalAs(UnmanagedType.LPStruct)> ByVal iid As Guid, _
     ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, <Out>
    <MarshalAs(UnmanagedType.IUnknown)> ByRef ppInterface As Object) As Integer
    End Interface

    <Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), _
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Public Interface IAudioEndpointVolume
        Function RegisterControlChangeNotify(ByVal pNotify As IntPtr) As Integer
        Function UnregisterControlChangeNotify(ByVal pNotify As IntPtr) As Integer
        Function GetChannelCount(ByRef pnChannelCount As UInteger) As Integer
        Function SetMasterVolumeLevel(ByVal fLevelDB As Single, _
        ByVal pguidEventContext As Guid) As Integer
        Function SetMasterVolumeLevelScalar_
        (ByVal fLevel As Single, ByVal pguidEventContext As Guid) As Integer
        Function GetMasterVolumeLevel(ByRef pfLevelDB As Single) As Integer
        Function GetMasterVolumeLevelScalar(ByRef pfLevel As Single) As Integer
    End Interface

    Friend Sub SetVolume(ByVal Level As Integer)
        Try
            Dim deviceEnumerator As IMMDeviceEnumerator = _
                                 MMDeviceEnumeratorFactory.CreateInstance()
            Dim speakers As IMMDevice = Nothing
            Dim res As Integer
            Const eRender = 0
            Const eMultimedia = 1
            deviceEnumerator.GetDefaultAudioEndpoint(eRender, eMultimedia, speakers)
            Dim Audio_EndPointVolume As IAudioEndpointVolume = Nothing
            speakers.Activate(GetType(IAudioEndpointVolume).GUID, 0, _
                              IntPtr.Zero, Audio_EndPointVolume)
            Dim ZeroGuid As New Guid()
            res = Audio_EndPointVolume.SetMasterVolumeLevelScalar_
                  (Level / 100.0F, ZeroGuid)
        Catch ex As Exception
        End Try
    End Sub

    Friend Function GetVolume() As Integer
        Try
            Dim currentLevel As Single = 0 ' Expressed as a decimal value
            Dim deviceEnumerator As IMMDeviceEnumerator = _
                                 MMDeviceEnumeratorFactory.CreateInstance()
            Dim speakers As IMMDevice = Nothing
            Dim res As Integer
            Const eRender = 0
            Const eMultimedia = 1
            deviceEnumerator.GetDefaultAudioEndpoint(eRender, eMultimedia, speakers)
            Dim Audio_EndPointVolume As IAudioEndpointVolume = Nothing
            speakers.Activate(GetType(IAudioEndpointVolume).GUID, _
                              0, IntPtr.Zero, Audio_EndPointVolume)
            res = Audio_EndPointVolume.GetMasterVolumeLevelScalar(currentLevel)
            Return CInt(100 * currentLevel)  ' Returned as an Integer 0 - 100
        Catch ex As Exception
            Return -1
        End Try
    End Function
End Module 
C#
using System;
using System.Runtime.InteropServices;

namespace SystemAudio
{
    internal static class WindowsSystemAudio
    {
        [ComImport]
        [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), 
               InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IMMDeviceEnumerator
        {
            void Vtbl();
            int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice);
        }
        private static class MMDeviceEnumeratorFactory
        {
            public static IMMDeviceEnumerator CreateInstance()
            {
                return (IMMDeviceEnumerator)Activator.CreateInstance
                (Type.GetTypeFromCLSID(new Guid
                ("BCDE0395-E52F-467C-8E3D-C4579291692E")));
            }
        }
        [Guid("D666063F-1587-4E43-81F1-B948E807363F"), 
               InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IMMDevice
        {
            int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, 
                          int dwClsCtx, IntPtr pActivationParams, 
                          [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
        }

        [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), 
               InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IAudioEndpointVolume
        {
            int RegisterControlChangeNotify(IntPtr pNotify);
            int UnregisterControlChangeNotify(IntPtr pNotify);
            int GetChannelCount(ref uint pnChannelCount);
            int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext);
            int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);
            int GetMasterVolumeLevel(ref float pfLevelDB);
            int GetMasterVolumeLevelScalar(ref float pfLevel);
        }

        internal static void SetVolume(int level)
        {
            try
            {
                IMMDeviceEnumerator deviceEnumerator = 
                                    MMDeviceEnumeratorFactory.CreateInstance();
                IMMDevice speakers;
                const int eRender = 0;
                const int eMultimedia = 1;
                deviceEnumerator.GetDefaultAudioEndpoint
                                 (eRender, eMultimedia, out speakers);
                object aepv_obj;
                speakers.Activate(typeof(IAudioEndpointVolume).GUID, 
                                  0, IntPtr.Zero, out aepv_obj);
                IAudioEndpointVolume aepv = (IAudioEndpointVolume)aepv_obj;
                Guid ZeroGuid = new();
                int res = aepv.SetMasterVolumeLevelScalar(level / 100f, ZeroGuid);
            }
            catch (Exception ex) 
            { 
            }
        }

        internal static int GetVolume()
        {
            try
            {
                float currentLevel = 0f;
                IMMDeviceEnumerator deviceEnumerator = 
                         MMDeviceEnumeratorFactory.CreateInstance();
                IMMDevice speakers;
                const int eRender = 0;
                const int eMultimedia = 1;
                deviceEnumerator.GetDefaultAudioEndpoint
                                 (eRender, eMultimedia, out speakers);
                object aepv_obj;
                speakers.Activate(typeof(IAudioEndpointVolume).GUID, 
                                  0, IntPtr.Zero, out aepv_obj);
                IAudioEndpointVolume aepv = (IAudioEndpointVolume)aepv_obj;
                int res = aepv.GetMasterVolumeLevelScalar(ref currentLevel);
                return (int)(100 * currentLevel);  // Returned as an Integer 0 - 100
            }
            catch (Exception ex) 
            { 
                return -1;
            }
        }
    }
}

Points of Interest

Loads of credit and a big thank you goes to Eske Rahn for the large amount of research that he did to gather the information and produce an example.

History

  • 4th April, 2023: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)