1
votes

I am developing a screen recording software and it has volume control. The code I pasted below is how I am controlling the volume.

static class NativeMethods
    {
        [DllImport("winmm.dll")]
        public static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);

        [DllImport("winmm.dll", EntryPoint = "waveOutSetVolume")]
        public static extern int WaveOutSetVolume(IntPtr hwo, uint dwVolume);

        [DllImport("winmm.dll", SetLastError = true)]
        public static extern bool PlaySound(string pszSound, IntPtr hmod, uint fdwSound);
    }


//Event for handling volume control
    private void VolumeSlider(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        // Calculate the volume that's being set
     int NewVolume = ((ushort.MaxValue / 10) * (int)slider.Value);
        // Set the same volume for both the left and the right channels
        uint NewVolumeAllChannels = (((uint)NewVolume & 0x0000ffff) | ((uint)NewVolume << 16));
        // Set the volume
        NativeMethods.WaveOutSetVolume(IntPtr.Zero, NewVolumeAllChannels);
    }

By viewing the Volume Mixer on Windows I can see this sets the application's volume and not the device. This is great because only changing the application's volume will change the volume of the video it's recording.

enter image description here

Now I want to know if it is possible to create a VU Meter for the application's volume like the one in Windows Volume Mixer. I have tried to achieve this effect using NAudio, but I'm not sure how or if it can. I am open to other APIs.

EDIT: I am not asking how to change the volume...I just need a functioning VU Meter like the on in the Mixer.

1
Its just a slider with a vertical progress bar overlay, should be simple to make... Are you talking about making the control, or making it appear in the sound tray? - Ron Beyer
Yes but how to I get the values for the VU Meter from the application (not the device) - Asix Jin
Not sure what the question is. Are you wanting to add it to the Windows Volume Mixer or are you trying to create your own control? I'd assume you'd just add a Slider to your UI, hook into the ValueChanged event to call VolumeSlider - Kcvin
You set the application's volume at app startup so you know the initial value, you save it when the application is closed. When opened again you load the previous volume and set the volume using the saved value. And you set Min and Max values on your Slider - Kcvin
So the question is how to get the currently output sound level from the application? - Ron Beyer

1 Answers

2
votes

Didn't want to leave this question unanswered in case someone else stumbles upon this. Basically @RickLiddle comment had the answer. I'll post my modified code from said answer and try to explain. Trying to learn this I have gotten a quite familiar with NAudio & CSCore so if you need further help don't hesitate to ask.

class PeakClass
{
    static int CurrentProcessID = 0000;

    private static void Main(string[] args)
    {
        //Basically gets your default audio device and session attached to it
        using (var sessionManager = GetDefaultAudioSessionManager2(DataFlow.Render))
        {
            using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
            {
                //This will go through a list of all processes uses the device
                //the code got two line above.
                foreach (var session in sessionEnumerator)
                {
                    //This block of code will get the peak value(value needed for VU Meter)
                    //For whatever process you need it for (I believe you can also check by name
                    //but I found that less reliable)
                    using (var session2 = session.QueryInterface<AudioSessionControl2>())
                    {
                        if(session2.ProcessID == CurrentProcessID)
                        {
                            using (var audioMeterInformation = session.QueryInterface<AudioMeterInformation>())
                            {
                                Console.WriteLine(audioMeterInformation.GetPeakValue());
                            }
                        }
                    }

                   //Uncomment this block of code if you need the peak values 
                   //of all the processes
                   //
                    //using (var audioMeterInformation = session.QueryInterface<AudioMeterInformation>())
                    //{
                    //    Console.WriteLine(audioMeterInformation.GetPeakValue());
                    //}
                }
            }
        }
    }

    private static AudioSessionManager2 GetDefaultAudioSessionManager2(DataFlow dataFlow)
    {
        using (var enumerator = new MMDeviceEnumerator())
        {
            using (var device = enumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia))
            {
                Console.WriteLine("DefaultDevice: " + device.FriendlyName);
                var sessionManager = AudioSessionManager2.FromMMDevice(device);
                return sessionManager;
            }
        }
    }
}