C#中使用WavHelper保存录音数据为wav文件

时间:2021-08-11
本文章向大家介绍C#中使用WavHelper保存录音数据为wav文件,主要包括C#中使用WavHelper保存录音数据为wav文件使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

C#将录音数据文件保存为wav格式文件,这里使用到的是WavHelper工具类。

WavHelper工具类:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WavHelperTool
{
    /// <summary>
    /// 生成wav文件的帮助类,本类来自网络,作者不详
    /// </summary>
    public class WavHelper : IDisposable
    {
        #region 变量
        private MyWaveFormat mWavFormat;
        private int mSampleCount = 0;
        private string mFileName = "";
        private FileStream mWaveFile = null;
        private BinaryWriter mWriter = null;
        private int _sampleRate = 0;
        private short _channels = 0;
        private string _filePath = "";
        #endregion

        public WavHelper(string audioFileName, int sampleRate, short channels)
        {
            _filePath = audioFileName;
            _sampleRate = sampleRate;
            _channels = channels;
            this.mFileName = audioFileName;
            mWavFormat = new MyWaveFormat();
            mWavFormat.SamplesPerSecond = _sampleRate;
            mWavFormat.BitsPerSample = 16;
            mWavFormat.Channels = _channels;
            mWavFormat.BlockAlign = (short)(mWavFormat.Channels * (mWavFormat.BitsPerSample / 8));
            mWavFormat.AverageBytesPerSecond = mWavFormat.BlockAlign * mWavFormat.SamplesPerSecond;
            Start();
        }

        /// <summary>
        /// 存放的录音文件路径
        /// </summary>
        public string FilePath
        {
            get { return _filePath; }
        }

        public void Dispose()
        {
            Stop();
        }

        /// <summary>
        /// 结束写入并关闭文件
        /// </summary>
        private void Stop()
        {
            // 写WAV文件尾  
            mWriter.Seek(4, SeekOrigin.Begin);
            mWriter.Write((int)(mSampleCount + 36));
            mWriter.Seek(40, SeekOrigin.Begin);
            mWriter.Write(mSampleCount);

            mWriter.Close();
            mWaveFile.Close();
            mWriter = null;
            mWaveFile = null;
        }

        /// <summary>  
        /// 创建保存的波形文件,并写入必要的文件头.  
        /// </summary>  
        private void Start()
        {
            // Open up the wave file for writing.  
            mWaveFile = new FileStream(mFileName, FileMode.Create);
            mWriter = new BinaryWriter(mWaveFile);
            /**************************************************************************  
               Here is where the file will be created. A  
               wave file is a RIFF file, which has chunks  
               of data that describe what the file contains.  
               A wave RIFF file is put together like this:  
               The 12 byte RIFF chunk is constructed like this:  
               Bytes 0 - 3 :  'R' 'I' 'F' 'F'  
               Bytes 4 - 7 :  Length of file, minus the first 8 bytes of the RIFF description.  
                                 (4 bytes for "WAVE" + 24 bytes for format chunk length +  
                                 8 bytes for data chunk description + actual sample data size.)  
                Bytes 8 - 11: 'W' 'A' 'V' 'E'  
                The 24 byte FORMAT chunk is constructed like this:  
                Bytes 0 - 3 : 'f' 'm' 't' ' '  
                Bytes 4 - 7 : The format chunk length. This is always 16.  
                Bytes 8 - 9 : File padding. Always 1.  
                Bytes 10- 11: Number of channels. Either 1 for mono,  or 2 for stereo.  
                Bytes 12- 15: Sample rate.  
                Bytes 16- 19: Number of bytes per second.  
                Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or  16 bit mono, 4 for 16 bit stereo.  
                Bytes 22- 23: Number of bits per sample.  
                The DATA chunk is constructed like this:  
                Bytes 0 - 3 : 'd' 'a' 't' 'a'  
                Bytes 4 - 7 : Length of data, in bytes.  
                Bytes 8 -: Actual sample data.  
              ***************************************************************************/
            // Set up file with RIFF chunk info.  
            char[] ChunkRiff = { 'R', 'I', 'F', 'F' };
            char[] ChunkType = { 'W', 'A', 'V', 'E' };
            char[] ChunkFmt = { 'f', 'm', 't', ' ' };
            char[] ChunkData = { 'd', 'a', 't', 'a' };

            short shPad = 1;                // File padding  
            int nFormatChunkLength = 0x10;  // Format chunk length.  
            int nLength = 0;                // File length, minus first 8 bytes of RIFF description. This will be filled in later.
            short shBytesPerSample = 0;     // Bytes per sample.  

            // 一个样本点的字节数目  
            if (8 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels)
                shBytesPerSample = 1;
            else if ((8 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels) || (16 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels))
                shBytesPerSample = 2;
            else if (16 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels)
                shBytesPerSample = 4;

            // RIFF 块  
            mWriter.Write(ChunkRiff);
            mWriter.Write(nLength);
            mWriter.Write(ChunkType);

            // WAVE块  
            mWriter.Write(ChunkFmt);
            mWriter.Write(nFormatChunkLength);
            mWriter.Write(shPad);
            mWriter.Write(mWavFormat.Channels);
            mWriter.Write(mWavFormat.SamplesPerSecond);
            mWriter.Write(mWavFormat.AverageBytesPerSecond);
            mWriter.Write(shBytesPerSample);
            mWriter.Write(mWavFormat.BitsPerSample);

            // 数据块  
            mWriter.Write(ChunkData);
            mWriter.Write((int)0);   // The sample length will be written in later.
        }

        /// <summary>
        /// 每当采集到音频数据时,将其写入
        /// </summary>
        /// <param name="data"></param>
        public void WriteAudioData(byte[] data)
        {
            mWriter.Write(data, 0, data.Length);
            mSampleCount += data.Length;
        }
    }

    public class MyWaveFormat
    {
        /// <summary>
        /// 采样率
        /// </summary>
        public int SamplesPerSecond;

        /// <summary>
        /// 采样位数
        /// </summary>
        public short BitsPerSample;

        /// <summary>
        /// 通道数
        /// </summary>
        public short Channels;

        /// <summary>
        /// 单位采样点的字节数
        /// </summary>
        public short BlockAlign;

        /// <summary>
        /// 每秒平均码率
        /// </summary>
        public int AverageBytesPerSecond;
    }
}

 C#保存调用:

//1、定义wav文件生成类
private WavHelper microphoneWav = null;

//2、初始化麦克风数据wav文件写入器
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "microphone.wav");//根目录下生成microphone.wav
microphoneWav = new WavHelper(path, sampleRate, channelCount);//保存路径、采样率、频道数

//3、数据写入wav文件中
byte[] data = "xxx";//比特数据
microphoneWav.WriteAudioData(data);

//4、关闭写入
microphoneWav.Dispose();
microphoneWav = null;

 总结:实践是检验真理的唯一标准。

原文地址:https://www.cnblogs.com/qiantao/p/15126990.html