2013-01-16 102 views
2

我正在尝试使用NAudio编写峰值音量表。我的代码与http://channel9.msdn.com/coding4fun/articles/NET-Voice-Recorder非常相似,但是我的代码和链接的录音机项目都遇到了问题。NAudio峰值音量表

当播放恒定频率和音量的声音时,音量表开始时会处于合理的水平,但会衰减到非常小的值。我不确定为什么会出现这种情况,因为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

我还没有检查过该项目,但它可能不是实际的峰值计。有几种类似“VU”的算法。 – Brad

+0

什么是“VU”类算法? –

+0

VU仪表(http://www.transitchicago.com/farechanges/)用于测量信号电平。针跟踪水平的方式不是瞬时的......它稍微滞后一点,平均了一些峰和谷。有些算法试图模拟这种行为。还有其他用于计量信号的算法。峰值计总是显示出您的样品组的最高水平。您链接到的项目可能会使用某种Delta算法,这就是为什么当没有变化时它会下降。这只是一个猜测,但我没有看过代码。 – Brad

回答

4

所有这一切都在那篇文章中发生的是,它是寻找在一个小的时间间隔(例如20毫秒)的最大音频峰值,然后绘制该以分贝为单位。要查找峰值,请检查间隔中每个样本的值,并选择最大值(这是SampleAggregator类正在做的)。要转换为分贝,取最大值的对数为10,然后乘以10.所以0dB是最大的,低于-96dB的任何值都是有效的。 (实际上,回头看文章,我不认为我甚至不打算转换为分贝比例,我可能应该这样做)

+0

我明白了。那么为什么我会在几秒钟后看到“音量”下降?我正在努力解释这种奇怪的行为。 –

+0

你绝对捕捉音频?您是否尝试过录制几秒钟,看看数值是否与预期一致 –

+0

我相信我正在捕获音频,因为当我最初开始说话时,音量会增加几秒钟。我用我的代码的适用部分更新了我的问题,如果这有帮助的话。显示的maxval和minval值开始在合理的水平,但在几秒钟后迅速下降到接近零。 –

1

这是我从输出设备获取峰值的小解决方案。我使用n音讯版本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)); 
     } 
    } 
} 
+0

它不工作,直到打开声音设置,任何线索为什么? – boy

0

试图让水平与MasterPeakValue似乎不仅仅是调用该方法,这违背了它的简单比较复杂。

我意外地意识到,即使您不使用传入数据,您也必须打开设备进行录制。由于您正在启动WaveIn,因此MasterPeakValue应返回非0值。

另一个简单的替代方法是打开系统录制设备的属性(右键单击系统音量图标并选择“录制设备”)。

(在2台不同的计算机上测试)

+0

很高兴知道!必须是内部的东西... – fvlinden