Displaying a Volume Meter using NAudio
Windows 7 has this volume meter in the system tray. I’m sure you’re pretty familiar with it.
It’s pretty cool. If you’re playing music, the green bar dances up and down, reflecting the volume of the music being played at the time.
If you’re developing an application that includes some form of multimedia, such as the ability to play music or listen to recorded phone calls, something simple like this is a great way to provide feedback to the user, showing that something is actually playing.
Typically, doing anything with sound in Windows is a messy business, as you’d have to play around with some pretty low-level APIs.To get an idea, just take a look at how many different ways there are to get master sound volume in C#.
Fortunately, there’s a managed library called NAudio which takes away a lot of the pain of dealing with this stuff. And quite conveniently, it’s available as a NuGet package.
After installing NAudio via NuGet, you can get a reference to your default audio output device using the following code:
var enumerator = new MMDeviceEnumerator();
var device = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console);
Note that there are three different values for Role
, but they don’t seem to make any difference.
Put a breakpoint at the end and hover over the device
variable to see that it’s bound to your actual output audio device:
From this, we can get a value that indicates the audio volume:
while (true)
{
Console.Write("\r{0}", device.AudioMeterInformation.MasterPeakValue);
}
I’m using the old \r
trick to overwrite the value displayed in the same line with each iteration. You’ll see that the volume displayed is a float
value:
That’s nice, but it’s a bit hard to visually interpret how it’s changing. Let’s build a simple volume meter in the console instead.
while (true)
{
var volume = device.AudioMeterInformation.MasterPeakValue;
var scale = (int)Math.Floor(volume * 79);
Console.Write("\r");
var sb = new StringBuilder();
sb.Append('-', scale);
sb.Append(' ', 79 - scale);
Console.Write(sb.ToString());
}
We can represent the volume meter as a series of dashes in a line in the command line. Since NAudio gives us a value between 0 and 1, we can scale that to something between 0 and 79 (since 80 characters fit in a line in the command line by default).
With that done, we can then:
- Print a
\r
character. This starts writing at the beginning of the line, essentially overwriting the previously drawn meter. - Print a number of dashes proportional to the scaled volume we just calculated. Since we’re using StringBuilder’s repeat ability, we don’t need loops.
- Print spaces for the rest of the line. This clears any leftover dashes from the previously drawn meter.
And there, you have it:
This screenshot doesn’t really do it justice. Since the meter is updating pretty much in real time, go ahead and run this program when you have music playing to see how nicely it dances.
Reference: | Displaying a Volume Meter using NAudio from our NCG partner Daniel DAgostino at the Gigi Labs blog. |