16

I'm having some issues with naudio and saving sound recordings. The code I currently have works to the point where it saves the wav file, but when I open it up, Windows Media Player returns an error: "Windows Media Player encountered a problem while playing the file"

I have two buttons, a "Record" button, which turns into the stop button after it's pressed. And I have a "Save" button which when clicked, saves the recording to 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;
}
Spencer
  • 612
  • 2
  • 12
  • 26
  • Can you show the code behind your 'stop' action please? Just need to see how you're closing off the `waveWriter` and such. – Corey Jul 31 '13 at 23:53
  • @Corey, I added the 'stop' action to the code. Cheers. – Spencer Jul 31 '13 at 23:59
  • OK, tested with similar code and all seems to be working for me. Are you stopping the recording before attempting to play it in WMP? – Corey Aug 01 '13 at 00:53
  • What I do is click the 'record' button and record my voice then click the stop button, then click the 'save' button. When I click the save button and open the wav file, there is no audio. – Spencer Aug 01 '13 at 00:58
  • Ah... that would explain it then. I thought that looked a bit hinky :P – Corey Aug 01 '13 at 01:26
  • Hehe. Any idea on how to fix it? – Spencer Aug 01 '13 at 01:28

1 Answers1

30

Your recordButton_Click code isn't recording, it's piping data from a WaveIn to a WaveOut, which will play the data coming from your source (microphone) directly to the output (speakers). It doesn't retain that data for later use, it just pipes it from one to the other. If you want to subsequently save that data to disk, you need to buffer it yourself.

The saveResponse_Click on the other hand is starting the direct recording of data from the microphone to a wave file on disk. If you click your Save Response button, wait for a bit, then click your Stop button, you should get a recorded wave file.

If you want to record directly to disk, this is fine. If you want to record to memory, then optionally write to disk, then you need to save the data as it comes in. Perhaps use a memory stream to hold the data while recording, then write that to the WaveFileWriter when it comes time to save the file.


Here's the code I used for testing direct recording to a wave file on disk:

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;
}
Corey
  • 15,524
  • 2
  • 35
  • 68
  • when i write your code, it is throwing exception and saying "BadDeviceId calling waveInOpen". any suggestion ? what is that error ? – abidinberkay Apr 07 '16 at 11:59
  • 1
    @abidinberkay the default DeviceNumber is 0, if that ID is bad, it probably means you have never plugged in a microphone. – Roger Willcocks Feb 16 '17 at 22:22