使用NAudio从麦克风录制声音并保存。

17

我在使用naudio录制音频并保存时遇到了一些问题。目前我的代码可以将wav文件保存,但是当我打开它时,Windows Media Player会返回一个错误:"Windows Media Player 在播放文件时遇到问题"。

我有两个按钮,一个是"Record"按钮,在按下后变成停止按钮。我还有一个"Save"按钮,当点击它时,将录制保存为sample.wav

NAudio.Wave.WaveIn sourceStream = null;
NAudio.Wave.DirectSoundOut waveOut = null;
NAudio.Wave.WaveFileWriter waveWriter = null;

private void recordButton_Click(object sender, EventArgs e)
{
    int deviceNumber = sourceList.SelectedItems[0].Index;

    sourceStream = new NAudio.Wave.WaveIn();
    sourceStream.DeviceNumber = deviceNumber;
    sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);

    NAudio.Wave.WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream);

    waveOut = new NAudio.Wave.DirectSoundOut();
    waveOut.Init(waveIn);

    sourceStream.StartRecording();
    waveOut.Play();

    recordButton.Visible = false;
    stopRecord.Visible = true;
}

private void saveResponse_Click(object sender, EventArgs e)
{
    int deviceNumber = sourceList.SelectedItems[0].Index;

    string saveLocation = "c:\\wav\\sample.wav";

    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(saveLocation, sourceStream.WaveFormat);

    sourceStream.StartRecording();

    MessageBox.Show("Recording successfully saved.");
}

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 stopRecord_Click(object sender, EventArgs e)
{
    if (waveOut != null)
    {
        waveOut.Stop();
        waveOut.Dispose();
        waveOut = null;
    }
    if (sourceStream != null)
    {
        sourceStream.StopRecording();
        sourceStream.Dispose();
        sourceStream = null;
    }
    if (waveWriter != null)
    {
        waveWriter.Dispose();
        waveWriter = null;
    }

    recordButton.Visible = true;
    stopRecord.Visible = false;
    saveResponse.Enabled = true;
}

你能展示一下“停止”操作的代码吗?我只需要看看你是如何关闭waveWriter等内容的。 - Corey
@Corey,我已经将“stop”操作添加到代码中了。干杯。 - Spencer
好的,我用类似的代码进行了测试,似乎一切正常。你在尝试在WMP中播放之前停止了录制吗? - Corey
我所做的是点击“录音”按钮,录制我的声音,然后单击停止按钮,最后单击“保存”按钮。当我单击保存按钮并打开wav文件时,没有任何音频。 - Spencer
啊...这样就能解释了。我觉得那看起来有点可疑 :P - Corey
呵呵。你有什么想法来解决这个问题吗? - Spencer
1个回答

31

你的recordButton_Click代码并没有进行录音,而是从一个WaveIn输入源中提取数据,通过WaveOut输出源播放来自你的麦克风的数据直接传输到输出设备(扬声器)。它不会保存那些数据以供后续使用,只是将其从一个设备传输到另一个设备。如果你想要随后将这些数据保存到磁盘上,你需要自己对这些数据进行缓冲处理。

而另一方面,saveResponse_Click函数则是开始将来自麦克风的数据直接录制到磁盘上的波形文件中。如果你点击Save Response按钮,稍等片刻,然后点击Stop按钮,你应该就可以得到一个录制好的波形文件。

如果你希望直接录制到磁盘上,那没问题。但是如果你想要将它录制到内存中,然后再选择性地将其写入磁盘,那么你需要在数据传输时就对它进行保存。你可以考虑使用内存流来保存这些数据,然后在需要保存文件时将其写入WaveFileWriter中。


这里是我用于测试将数据直接录制到磁盘上的代码:

public WaveIn waveSource = null;
public WaveFileWriter waveFile = null;

private void StartBtn_Click(object sender, EventArgs e)
{
    StartBtn.Enabled = false;
    StopBtn.Enabled = true;

    waveSource = new WaveIn();
    waveSource.WaveFormat = new WaveFormat(44100, 1);

    waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
    waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);

    waveFile = new WaveFileWriter(@"C:\Temp\Test0001.wav", waveSource.WaveFormat);

    waveSource.StartRecording();
}

private void StopBtn_Click(object sender, EventArgs e)
{
    StopBtn.Enabled = false;

    waveSource.StopRecording();
}

void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
    if (waveFile != null)
    {
        waveFile.Write(e.Buffer, 0, e.BytesRecorded);
        waveFile.Flush();
    }
}

void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
{
    if (waveSource != null)
    {
        waveSource.Dispose();
        waveSource = null;
    }

    if (waveFile != null)
    {
        waveFile.Dispose();
        waveFile = null;
    }

    StartBtn.Enabled = true;
}

当我编写您的代码时,它会抛出异常并显示“BadDeviceId calling waveInOpen”。有什么建议吗?这是什么错误? - abidinberkay
1
@abidinberkay 默认的设备编号为0,如果该ID错误,很可能是因为您从未连接麦克风。 - Roger Willcocks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接