[英]recording wave naudio liblary - poor quality of sound
我正在使用 naudio(使用教程)學習音頻編程。 我的程序(C# .net winForms)我有記錄和停止按鈕。 代碼如下所示:
NAudio.Wave.WaveIn sourceStream = null;
NAudio.Wave.WaveFileWriter waveWriter = null;
private void RecordButton_Click(object sender, EventArgs e)
{
int deviceNumber = 0;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
waveWriter = new NAudio.Wave.WaveFileWriter("d:\\a.wav", sourceStream.WaveFormat);
sourceStream.StartRecording();
}
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (waveWriter == null) return;
waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
waveWriter.Flush();
}
private void StopButton_Click(object sender, EventArgs e)
{
waveWriter.Dispose();
waveWriter = null;
}
它可以工作,但波形文件質量不好 - 我錄制的聲音有很小的差距。 我想要 44100 Hz 的采樣率和 16 位的采樣格式。
我無法完全復制您發現的內容,但我確實注意到DataAvailable
事件並沒有為其他操作留下太多空間。 一個簡單的Thread.Sleep(100);
停止應用程序。
假設您的連續寫入(和刷新)可能會導致問題,我實現了一個原始Queue
,該Queue
保留要寫入的字節並使用線程池中的線程進行實際寫入。
DataAvailable
事件現在看起來像這樣:
Queue<byte[]> writebuffer = new Queue<byte[]>();
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (waveWriter == null) return;
byte[] realbytes = new byte[e.BytesRecorded];
Array.Copy(e.Buffer, realbytes, e.BytesRecorded);
writebuffer.Enqueue(realbytes);
}
在StartRecording
調用之后,我將任務排隊以讀取隊列並將數據寫入流。 如果我在那里添加延遲,應用程序就不再停止。
ThreadPool.QueueUserWorkItem((s) =>
{
var keeprunning = true;
sourceStream.RecordingStopped += (rss, rse) => { keeprunning = false; };
while(keeprunning)
{
if (writebuffer.Count==0)
{
Thread.Sleep(0);
}
else
{
var buf = writebuffer.Dequeue();
waveWriter.Write(buf,0,buf.Length);
// Thread.Sleep(100); // for testing
}
}
waveWriter.Dispose();
waveWriter = null;
});
我也遇到過這個問題。 解決方案是從使用 WaveIn 進行錄制切換到 WasapiCapture。 設置和使用幾乎相同,但質量要好得多。 試試這個:
public class Recorder
{
public string _outputFolder { get; set; }
public string _outputFilePath { get; set; }
public WasapiCapture _capture { get; set; }
public WaveFileWriter _writer { get; set; }
public Recorder()
{
_outputFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "NAudio");
Directory.CreateDirectory(_outputFolder);
_outputFilePath = Path.Combine(_outputFolder, "recorded.wav");
}
public void StartRecording()
{
_capture = new WasapiCapture();
_capture.ShareMode = AudioClientShareMode.Shared;
_capture.WaveFormat = new WaveFormat(44100, 32, 1);
_writer = new WaveFileWriter(_outputFilePath, _capture.WaveFormat);
_capture.DataAvailable += _capture_DataAvailable;
_capture.RecordingStopped += _capture_RecordingStopped; ;
_capture.StartRecording();
}
public void StopRecording()
{
_capture.StopRecording();
}
private void _capture_DataAvailable(object sender, WaveInEventArgs e)
{
_writer.Write(e.Buffer, 0, e.BytesRecorded);
}
private void _capture_RecordingStopped(object sender, StoppedEventArgs e)
{
_writer?.Dispose();
_writer = null;
_capture.Dispose();
_capture = null;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.