录音波naudio liblary - 声音质量差

时间:2012-05-24 17:10:20

标签: c# .net audio naudio wave

我正在使用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位。

2 个答案:

答案 0 :(得分:1)

我无法完全复制你发现的内容,但我注意到var tabs = require("sdk/tabs"); var xultabs = require("sdk/tabs/utils"); var viewFor = require("sdk/view/core").viewFor; var itemid = "my-extension-name"; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; // global variable to hold tab URL and function to set it on right-click of tab taburl = ""; function getTabURL(e) { taburl = xultabs.getTabURL(e.target); } tabs.on('ready', function(tab) { // set up event listener to get tab URL when tab is right-clicked let vtab = viewFor(tab); vtab.addEventListener("contextmenu", getTabURL); // add our context menu item if it's not already there let doc = viewFor(tab.window).document; if (!doc.getElementById(itemid)) { let menu = doc.getElementById("tabContextMenu"); let item = doc.createElementNS(xulns, "menuseparator"); menu.appendChild(item); item = doc.createElementNS(xulns, "menuitem"); item.setAttribute("label", "My Menu Item"); item.setAttribute("id", itemid); item.addEventListener("command", function() { pushURL(taburl) }); menu.appendChild(item); } }); function pushURL(url) { // pushes the URL to the service } 事件并没有为其他操作留下太多空间。一个简单的DataAvailable会拖延应用程序。

假设您的连续写入(和刷新)可能导致该问题,我实现了一个天真的Thread.Sleep(100);,它保留了要写入的字节,并使用线程池中的线程来进行实际写入。

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

答案 1 :(得分:0)

我也遇到了这个问题。解决方案是从使用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;
    }

}