NAudio Peak Volume Meter
Solution 1
All that is happening in that article is that it is finding the maximum audio peak over a small interval (e.g. 20ms) and then plotting that on a decibel scale. To find the peak, examine the value of each sample in the interval and select the max value (It's what the SampleAggregator
class is doing). To convert to decibels, take the log base 10 of the maximum value, and multiply by 10. So 0dB is the loudest, and anything below say -96dB is effectively silence. (actually, looking back at the article, I don't think I even bothered to convert to a decibel scale, which I probably should have done)
Solution 2
This was my little solution for getting peak from output device. I'm using NAudio version 1.7.0.15
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
var devices = enumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active);
comboboxDevices.Items.AddRange(devices.ToArray());
}
private void timer1_Tick(object sender, EventArgs e)
{
if (comboboxDevices.SelectedItem != null)
{
var device = (MMDevice)comboboxDevices.SelectedItem;
progressBar1.Value = (int)(Math.Round(device.AudioMeterInformation.MasterPeakValue * 100));
}
}
}
Shivam Sarodia
Updated on June 08, 2022Comments
-
Shivam Sarodia about 2 years
I'm attempting to write a peak volume meter using NAudio. My code is very similar to http://channel9.msdn.com/coding4fun/articles/NET-Voice-Recorder, but both my code and the linked Voice Recorder project suffer from an issue.
When playing a sound of constant frequency and volume, the volume meter initially begins at a reasonable level, but then decays to a very small value. I'm not sure why this is the case, for the peak volume meter in the NAudioDemo does not do this. I attempted to replicate the code from NAudioDemo in my program, but I was unable to find the code file containing the peak volume meter code.
Can somebody guide me to an alternative solution for creating a peak volume meter or help me determine why my solution (and the one provided at the link) both don't work?
public MainWindow() { int waveInDevices = WaveIn.DeviceCount; for (int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++) { WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice); Console.WriteLine("Device {0}: {1}, {2} channels", waveInDevice, deviceInfo.ProductName, deviceInfo.Channels); WaveIn waveIn = new WaveIn(); waveIn.DeviceNumber = 0; //TODO: Let the user choose which device, this comes from the device numbers above waveIn.DataAvailable += waveIn_DataAvailable; int sampleRate = SAMPLE_RATE; // 8 kHz int channels = 1; // mono waveIn.WaveFormat = new WaveFormat(sampleRate, channels); waveIn.StartRecording(); } } void waveIn_DataAvailable(object sender, WaveInEventArgs e) { for (int index = 0; index < e.BytesRecorded; index += 2) { short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]); float sample32 = sample / 32768f; ProcessSample(sample32); } } void ProcessSample(float sample1) { samplenumber += 1; if (sample1 > maxval) { maxval = sample1; } if (sample1 < minval) { minval = sample1; } //Run updateView every few loops if (samplenumber > (double)SAMPLE_RATE / DISPLAY_UPDATE_RATE) { samplenumber = 0; updateView(); //needs to be fast! } } void updateView() { Console.WriteLine(maxval); Console.WriteLine(minval); progressBar1.Value = (maxval - minval)*50; maxval = 0; minval = 0; }