naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.37k stars 1.09k forks source link

Not a standard WAVE PCM soundfile format #1132

Open eugeneYz opened 3 months ago

eugeneYz commented 3 months ago

I used standard 16bit,16KHz,Mono format to record WAV file. However, when parsing the audio file, the file header verified that the Subchunk1Size was 18 and reported an error.

Subchunk1Size: 16 for PCM. This is the size of the rest of the Subchunk which follows this number. form https://ccrma.stanford.edu/courses/422-winter-2014/projects/WaveFormat/

The following is my recording code, please help to see how to modify it to meet the standard pcm file header.

public class NAudioHelper : NotifyPropertyBase
{
    private WaveIn waveSource = null;
    public Action<byte[]> PcmDataAvailable;
    private readonly object waveSourceLock = new ();
    private WaveFileWriter writer;

    /// <summary>
    /// 录音保存至本地filePath
    /// </summary>
    /// <param name="filePath"></param>
    public void StartRec(string filePath)
    {
        waveSource = new WaveIn();
        waveSource.WaveFormat = new WaveFormat(16000, 16, 1); // 16bit,16KHz,Mono的录音格式
        writer = new WaveFileWriter(filePath, waveSource.WaveFormat);
        waveSource.DataAvailable += FileWriterRecording;
        waveSource.RecordingStopped += FileWriterRecordingStopped;
        waveSource.StartRecording();
    }

    /// <summary>
    /// 停止录音
    /// </summary>
    public void StopRec()
    {
        lock (waveSourceLock)
        {
            try
            {
                waveSource?.StopRecording();
                // Close Wave(Not needed under synchronous situation)
                waveSource?.Dispose();
                waveSource = null;
            }
            catch (Exception e) { Log.Add(e); }
        }
    }

    private void FileWriterRecording(object sender, WaveInEventArgs e)
    {
        writer?.Write(e.Buffer, 0, e.BytesRecorded);
    }

    private void FileWriterRecordingStopped(object sender, StoppedEventArgs e)
    {
        writer?.Close();
        writer?.Dispose();
        writer = null;
    }