我正在尝试使用NAudio编写峰值音量表。我的代码与http://channel9.msdn.com/coding4fun/articles/NET-Voice-Recorder非常相似,但我的代码和链接的录音机项目都存在问题。
当播放恒定频率和音量的声音时,音量计最初开始于合理的水平,但随后衰减到非常小的值。我不确定为什么会这样,因为NAudioDemo中的峰值音量表不会这样做。我试图在我的程序中复制NAudioDemo中的代码,但是我无法找到包含峰值音量计代码的代码文件。
有人可以指导我使用替代解决方案来创建峰值音量计,或者帮助我确定为什么我的解决方案(以及链接中提供的解决方案)都不起作用?
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;
}
答案 0 :(得分:5)
该文章中发生的一切是它在一个小间隔(例如20ms)内找到最大音频峰值,然后以分贝标度绘制。要查找峰值,请检查区间中每个样本的值并选择最大值(这是SampleAggregator
类正在执行的操作)。要转换为分贝,请取最大值的对数基数10,然后乘以10.因此,0dB是最大的,低于-96dB的任何值都是有效的静音。 (实际上,回头看这篇文章,我觉得我甚至不愿意转换成分贝比例,我可能应该这样做)
答案 1 :(得分:1)
这是我从输出设备获得峰值的小解决方案。我使用NAudio版本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));
}
}
}
答案 2 :(得分:0)
尝试使用MasterPeakValue获取级别似乎比调用方法更复杂,这会使其简单化。
我意外地意识到您必须打开设备进行录制,即使您不使用传入数据也是如此。由于您正在启动WaveIn,因此MasterPeakValue应返回非0值。
一个简单的选择,仅用于测试,是打开系统录音设备的属性(右键单击系统音量图标并选择&#34;录音设备&#34;)。
(在两台不同的计算机上测试过。)