简体   繁体   English

记录波 naudio 库 - 声音质量差

[英]recording wave naudio liblary - poor quality of sound

i'm lerning audio programming using naudio (using tutorial).我正在使用 naudio(使用教程)学习音频编程。 Im my program (C# .net winForms) I have record and stop button.我的程序(C# .net winForms)我有记录和停止按钮。 The code looks like that:代码如下所示:

    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;       
    }

It works but wave file quality isn't good - there are small gaps in sound i recorded.它可以工作,但波形文件质量不好 - 我录制的声音有很小的差距。 I want sample rate 44100 Hz and sample format 16-bit.我想要 44100 Hz 的采样率和 16 位的采样格式。

I couldn't exactly replicate what you found but I did notice that the DataAvailable event doesn't leave much room to be blocked for other operations.我无法完全复制您发现的内容,但我确实注意到DataAvailable事件并没有为其他操作留下太多空间。 A simple Thread.Sleep(100);一个简单的Thread.Sleep(100); stalls the application.停止应用程序。

Assuming your continuous writing (and flushing) might contribute to the issue I implemented a naive Queue that keeps the bytes to be written and use a thread from the threadpool to do the actual writing.假设您的连续写入(和刷新)可能会导致问题,我实现了一个原始Queue ,该Queue保留要写入的字节并使用线程池中的线程进行实际写入。

The DataAvailable event now looks like this: 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);
    }

Just after the StartRecording call I queue the task for reading the queue and writing the data to the stream.StartRecording调用之后,我将任务排队以读取队列并将数据写入流。 If I add a delay there the application no longer stalls.如果我在那里添加延迟,应用程序就不再停止。

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;
});

I experienced this issue as well.我也遇到过这个问题。 The solution was to switch from using WaveIn for the recording to WasapiCapture.解决方案是从使用 WaveIn 进行录制切换到 WasapiCapture。 The setup and usage is almost the same but the quality if far better.设置和使用几乎相同,但质量要好得多。 Try this:试试这个:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM