2013-01-16 138 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