首页 > 代码库 > Wav文件操作类

Wav文件操作类

    internal class WaveFile    {        #region 字段和属性        //文件路径        private string filepath;        //文件详情对象        private FileInfo fileInfo;        //文件流        private FileStream fileStream;        private byte[] fileByteData;        //临时存放byte数组        private byte[] tempByte;        //是否需要追加信息的标记        private Boolean isNeedAppend;        private DataBlock dataBlock;        /// <summary>        /// Data块        /// </summary>        public DataBlock Data        {            get { return dataBlock; }        }        private FactBlock factBlock;        /// <summary>        /// fact块        /// </summary>        public FactBlock Fact        {            get { return factBlock; }        }        private FmtBlock fmtBlock;        /// <summary>        /// fmt块        /// </summary>        public FmtBlock Format        {            get { return fmtBlock; }        }        private RiffBlock riffBlock;        /// <summary>        /// riff块        /// </summary>        public RiffBlock Riff        {            get { return riffBlock; }        }        /// <summary>        /// 记录文件长度        /// </summary>        public float FileLenth        {            get { return (float)dataBlock.DataSize / (float)fmtBlock.AverageBytesPerSec; }        }        private Boolean isWave;        /// <summary>        /// 记录是否是正确的wave文件        /// </summary>        public Boolean IsWAVE        {            get { return isWave; }        }        #endregion        /// <summary>        /// 构造函数        /// </summary>        /// <param name="inFilepath"></param>        public WaveFile(String inFilepath)        {            tempByte = new byte[4];            filepath = inFilepath;            riffBlock = new RiffBlock();            fmtBlock = new FmtBlock();            factBlock = new FactBlock();            dataBlock = new DataBlock();            fileInfo = new FileInfo(inFilepath);            fileStream = new FileStream(inFilepath, FileMode.Open, FileAccess.ReadWrite);// m_FileInfo.OpenRead();            fileByteData = new byte[fileStream.Length];            fileStream.Read(fileByteData, 0, (int)fileStream.Length);            fileStream.Dispose();            if(JudgeIsHaveFmt(fileByteData))            {                if (!JudgeFmtIsRight(fileByteData))                {                    fileInfo = new FileInfo(inFilepath);                    fileStream = new FileStream(inFilepath, FileMode.Open, FileAccess.ReadWrite);// m_FileInfo.OpenRead();                    fileByteData = new byte[fileStream.Length];                    fileStream.Read(fileByteData, 0, (int)fileStream.Length);                    fileStream.Dispose();                }            }            else            {                isWave = false;                return;            }            Read(fileByteData);            Dispose();            //Read(fileStream);            //fileStream.Dispose();        }         /// <summary>        /// 判断是否有fmt块        /// </summary>        /// <param name="byteData"></param>        private bool JudgeIsHaveFmt(byte[] byteData)        {            byte[] temp = new byte[4];            int index = 12;            for (int i = 0; i < 4; i++)            {                temp[i] = byteData[index];                index++;            }            if (temp[0] != WaveMark.szRiffFormat[0] || temp[1] != WaveMark.szRiffFormat[1] || temp[2] != WaveMark.szRiffFormat[2] || temp[3] != WaveMark.szRiffFormat[3])                return false;            return true;        }        /// <summary>        /// 判断fmt块是否正确 不正确的话,重新生成文件        /// </summary>        /// <param name="byteData"></param>        private bool JudgeFmtIsRight(byte[] byteData)        {            #region format块            fmtBlock.FmtSize = System.BitConverter.ToUInt32(byteData, 16);            fmtBlock.FmtTag = System.BitConverter.ToUInt16(byteData, 20);            if ((fmtBlock.FmtTag == 6 || fmtBlock.FmtTag == 7) && fmtBlock.FmtSize == 16)            {                byteData[16] = 18;                byte[] tempByteData = http://www.mamicode.com/new byte[byteData.Length + 2];                for (int i = 0; i < 16 + 20; i++)                {                    tempByteData[i] = byteData[i];                }                tempByteData[36] = 0;                tempByteData[37] = 0;                for (int i = 36; i < byteData.Length; i++)                {                    tempByteData[i+2] = byteData[i];                }                File.WriteAllBytes(filepath,tempByteData);                return false;            }            return true;            #endregion        }        /// <summary>        /// 通过byte[]来读取数据        /// </summary>        private void Read(byte[] byteData)        {            #region riff块            isWave = false;            for (int i = 0; i < 4; i++)            {                riffBlock.RiffID[i] = byteData[i];            }            if (riffBlock.RiffID[0] != WaveMark.szRiffID[0] || riffBlock.RiffID[1] != WaveMark.szRiffID[1] || riffBlock.RiffID[2] != WaveMark.szRiffID[2] || riffBlock.RiffID[3] != WaveMark.szRiffID[3])            {                return;            }            riffBlock.RiffSize = System.BitConverter.ToUInt32(byteData, 4);            if ((uint)fileInfo.Length - 8 != riffBlock.RiffSize)            {                //return;            }            int y = 0;            for (int i = 8; i < 12; i++)            {                riffBlock.RiffFormat[y] = byteData[i];                y++;            }            #endregion            #region format块            y = 0;            for (int i = 12; i < 16; i++)            {                fmtBlock.FmtID[y] = byteData[i];                y++;            }            if (fmtBlock.FmtID[0] != WaveMark.szRiffFormat[0] || fmtBlock.FmtID[1] != WaveMark.szRiffFormat[1] || fmtBlock.FmtID[2] != WaveMark.szRiffFormat[2] || fmtBlock.FmtID[3] != WaveMark.szRiffFormat[3])                return;            fmtBlock.FmtSize = System.BitConverter.ToUInt32(byteData, 16);            fmtBlock.FmtTag = System.BitConverter.ToUInt16(byteData, 20);            fmtBlock.Channels = System.BitConverter.ToUInt16(byteData, 22);            fmtBlock.SamplesPerSec = System.BitConverter.ToUInt32(byteData, 24);            fmtBlock.AverageBytesPerSec = System.BitConverter.ToUInt32(byteData, 28);            fmtBlock.BlockAlign = System.BitConverter.ToUInt16(byteData, 32);            fmtBlock.BitsPerSample = System.BitConverter.ToUInt16(byteData, 34);            #endregion            #region fact块            y = 0;            int index = (int)fmtBlock.FmtSize + 20;            for (int i = index; i < index + 4; i++)            {                tempByte[y] = byteData[i];                y++;            }            index = index + 4;            factBlock.FactID = tempByte;            if (factBlock.FactID[0] == WaveMark.factID[0] && factBlock.FactID[1] == WaveMark.factID[1] && factBlock.FactID[2] == WaveMark.factID[2] && factBlock.FactID[3] == WaveMark.factID[3])            {                #region  Fact_Chunk                factBlock.Size = System.BitConverter.ToUInt32(byteData, index);                index = index + 4;                index = index +(int)factBlock.Size;                #endregion                y = 0;                for (int i = index; i < index + 4; i++)                {                    tempByte[y] = byteData[i];                    y++;                }                index = index + 4;            }            #endregion            #region data块            dataBlock.DataID = tempByte;            if (dataBlock.DataID[0] == WaveMark.dataID[0] && dataBlock.DataID[1] == WaveMark.dataID[1] && dataBlock.DataID[2] == WaveMark.dataID[2] && dataBlock.DataID[3] == WaveMark.dataID[3])            {                y = 0;                for (int i = index; i < index + 4; i++)                {                    tempByte[y] = byteData[i];                    y++;                }                index = index + 4;                dataBlock.DataSize = BitConverter.ToUInt32(tempByte, 0);            }            dataBlock.DataArray = new Int16[dataBlock.DataSize];            dataBlock.NumSamples = (int)(dataBlock.DataSize);            dataBlock.ByteDataArray = new byte[dataBlock.DataSize];            int z = 0;            for (int i = index; z< dataBlock.DataSize; i++)            {                dataBlock.ByteDataArray[z] = byteData[i];                z++;            }                        if (fmtBlock.FmtTag == 1)//pcm数据            {                dataBlock.NumSamples = (int)(dataBlock.DataSize / 2);                for (int i = 0; i < dataBlock.NumSamples; i++)                {                    dataBlock.DataArray[i] = System.BitConverter.ToInt16(byteData, index);// byteData[index];                    index += 2;                }            }            else            {                byte[] bytedata = http://www.mamicode.com/new byte[dataBlock.DataSize];                y = 0;                for (int i = index; y < dataBlock.DataSize; i++)                {                    bytedata[y] = byteData[i];                    y++;                }                dataBlock.NumSamples = (int)(dataBlock.DataSize);                if (fmtBlock.FmtTag == 6)//alaw数据                {                    for (int i = 0; i < dataBlock.NumSamples; i++)                    {                        dataBlock.DataArray[i] = (short)AlawToPcm(bytedata[i]);                    }                }                if (fmtBlock.FmtTag == 7)//ulaw数据                {                    for (int i = 0; i < dataBlock.NumSamples; i++)                    {                        dataBlock.DataArray[i] = (short)UlawToPCM(bytedata[i]);                    }                }            }            isWave = true;            #endregion        }        /// <summary>        /// 读取数据        /// </summary>        private void Read(FileStream inFS)        {            #region riff块            isWave = false;            inFS.Read(riffBlock.RiffID, 0, 4);            if (riffBlock.RiffID[0] != WaveMark.szRiffID[0] || riffBlock.RiffID[1] != WaveMark.szRiffID[1] || riffBlock.RiffID[2] != WaveMark.szRiffID[2] || riffBlock.RiffID[3] != WaveMark.szRiffID[3])            {                return;            }            BinaryReader binRead = new BinaryReader(inFS);            riffBlock.RiffSize = binRead.ReadUInt32();            if ((uint)fileInfo.Length - 8 != riffBlock.RiffSize)            {                //return;            }            inFS.Read(riffBlock.RiffFormat, 0, 4);            #endregion            #region format块            inFS.Read(fmtBlock.FmtID, 0, 4);            if (fmtBlock.FmtID[0] != WaveMark.szRiffFormat[0] || fmtBlock.FmtID[1] != WaveMark.szRiffFormat[1] || fmtBlock.FmtID[2] != WaveMark.szRiffFormat[2] || fmtBlock.FmtID[3] != WaveMark.szRiffFormat[3])                return;            fmtBlock.FmtSize = binRead.ReadUInt32();            fmtBlock.FmtTag = binRead.ReadUInt16();            fmtBlock.Channels = binRead.ReadUInt16();            fmtBlock.SamplesPerSec = binRead.ReadUInt32();            fmtBlock.AverageBytesPerSec = binRead.ReadUInt32();            fmtBlock.BlockAlign = binRead.ReadUInt16();            fmtBlock.BitsPerSample = binRead.ReadUInt16();            // This accounts for the variable format header size              // 12 bytes of Riff Header, 4 bytes for FormatId, 4 bytes for FormatSize & the Actual size of the Format Header              inFS.Seek(fmtBlock.FmtSize + 20, System.IO.SeekOrigin.Begin);            #endregion            #region fact块            inFS.Read(tempByte, 0, 4);            factBlock.FactID = tempByte;            if (factBlock.FactID[0] == WaveMark.factID[0] && factBlock.FactID[1] == WaveMark.factID[1] && factBlock.FactID[2] == WaveMark.factID[2] && factBlock.FactID[3] == WaveMark.factID[3])            {                #region  Fact_Chunk                inFS.Read(tempByte, 0, 4);                factBlock.Size = BitConverter.ToUInt32(tempByte, 0);                inFS.Position += factBlock.Size;                #endregion                inFS.Read(tempByte, 0, 4);            }            #endregion            #region data块            dataBlock.DataID = tempByte;            if (dataBlock.DataID[0] == WaveMark.dataID[0] && dataBlock.DataID[1] == WaveMark.dataID[1] && dataBlock.DataID[2] == WaveMark.dataID[2] && dataBlock.DataID[3] == WaveMark.dataID[3])            {                inFS.Read(tempByte, 0, 4);                dataBlock.DataSize = BitConverter.ToUInt32(tempByte, 0);                //if (m_Data.DataSize != (uint)m_FileInfo.Length - (uint)inFS.Position)                //{                //    uint size2 = (uint)m_FileInfo.Length - (uint)inFS.Position;                //    byte[] bpara = System.BitConverter.GetBytes(size2);                //    inFS.Seek(inFS.Position - 4, SeekOrigin.Begin);//定位文件头                //    foreach (byte bt in bpara)                //        inFS.WriteByte(bt);                //}            }            else            {                //wave文件数据                dataBlock.DataSize = riffBlock.RiffSize + 8 - (uint)inFS.Position;            }            //m_Data.DataSize = (uint)m_FileInfo.Length - (uint)inFS.Position;             dataBlock.DataArray = new Int16[dataBlock.DataSize];            dataBlock.NumSamples = (int)(dataBlock.DataSize);            if (fmtBlock.FmtTag == 1)//pcm数据            {                inFS.Seek(40, System.IO.SeekOrigin.Begin);                dataBlock.NumSamples = (int)(dataBlock.DataSize / 2);                for (int i = 0; i < dataBlock.NumSamples; i++)                {                    dataBlock.DataArray[i] = binRead.ReadInt16();                }            }            else            {                byte[] bytedata = http://www.mamicode.com/new byte[dataBlock.DataSize];                inFS.Read(bytedata, 0, (int)dataBlock.DataSize);                dataBlock.NumSamples = (int)(dataBlock.DataSize);                if (fmtBlock.FmtTag == 6)//alaw数据                {                    for (int i = 0; i < dataBlock.NumSamples; i++)                    {                        dataBlock.DataArray[i] = (short)AlawToPcm(bytedata[i]);                    }                }                if (fmtBlock.FmtTag == 7)//ulaw数据                {                    for (int i = 0; i < dataBlock.NumSamples; i++)                    {                        dataBlock.DataArray[i] = (short)UlawToPCM(bytedata[i]);                    }                }            }            isWave = true;            #endregion        }        /// <summary>        /// 释放资源        /// </summary>        public void Dispose()        {            fileInfo = null;            fileStream.Dispose();        }        #region alaw转pcm 、ulaw转pcm        /// <summary>        /// alaw转pcm        /// </summary>        /// <param name="a_val"></param>        /// <returns></returns>        private int AlawToPcm(byte a_val)        {            int t;            int seg;            a_val ^= 0x55;            t = (a_val & 0xf) << 4;            seg = (a_val & 0x70) >> 4;            switch (seg)            {                case 0:                    t += 8;                    break;                case 1:                    t += 0x108;                    break;                default:                    t += 0x108;                    t <<= seg - 1;                    break;            }            if ((a_val & 0x80) == 0)            {                return -t;            }            return t;            //return ((a_val & 0x80) ? t : -t);        }        /// <summary>        /// ulaw转pcm        /// </summary>        /// <param name="u_val"></param>        /// <returns></returns>        private int UlawToPCM(byte u_val)        {            int t;            int u = (int)u_val;            /* Complement to obtain normal u-law value. */            u = ~u;            t = ((u & 0xf) << 3) + 0x84;            t <<= (u & 0x70) >> 4;            if ((u & 0x80) == 0)                return t - 0x84;            return (0x84 - t);        }        #endregion        #region 类: riff、fmt、fact、data        /// <summary>         /// riff块        /// </summary>         public class RiffBlock        {            public RiffBlock()            {                m_RiffID = new byte[4];                m_RiffFormat = new byte[4];            }            private byte[] m_RiffID;            //文件前四个字节 为RIFF             public byte[] RiffID            {                get { return m_RiffID; }                set { m_RiffID = value; }            }            private uint m_RiffSize;            /// <summary>             /// 数据大小 文件大小= 这个数字+8             /// </summary>              public uint RiffSize            {                get { return m_RiffSize; }                set { m_RiffSize = value; }            }            private byte[] m_RiffFormat;            /// <summary>            /// wave            /// </summary>            public byte[] RiffFormat            {                get { return m_RiffFormat; }                set { m_RiffFormat = value; }            }        }        /// <summary>         /// format块        /// </summary>         public class FmtBlock        {            public FmtBlock()            {                fmtID = new byte[4];            }            private byte[] fmtID;            /// <summary>             /// 固定为  是"fmt "            /// 以‘fmt ‘作为标示            /// </summary>              public byte[] FmtID            {                get { return fmtID; }                set { fmtID = value; }            }            private uint fmtSize;            /// <summary>             /// 一般情况下Size为16,此时最后附加信息没有;如果为18            /// 则最后多了2个字节的附加信息            /// </summary>              public uint FmtSize            {                get { return fmtSize; }                set { fmtSize = value; }            }            private ushort fmtTag;            /// <summary>            /// fmt            /// </summary>            public ushort FmtTag            {                get { return fmtTag; }                set { fmtTag = value; }            }            private ushort channels;            /// <summary>            /// 声道数            /// </summary>            public ushort Channels            {                get { return channels; }                set { channels = value; }            }            private uint samplesPerSec;            // 采样率(每秒样本数),表示每个通道的播放速度,            public uint SamplesPerSec            {                get { return samplesPerSec; }                set { samplesPerSec = value; }            }            private uint averageBytesPerSec;            /// <summary>             /// 波形音频数据传送速率,其值为通道数*每秒数据位数*每样            /// 本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。             /// </summary>              public uint AverageBytesPerSec            {                get { return averageBytesPerSec; }                set { averageBytesPerSec = value; }            }            private ushort blockAlign;            public ushort BlockAlign            {                get { return blockAlign; }                set { blockAlign = value; }            }            private ushort bitsPerSample;            /// <summary>             ///  每样本的数据位数,表示每个声道中各个样本的数据位数。如果有多            /// 个声道,对每个声道而言,样本大小都一样。              /// </summary>              public ushort BitsPerSample            {                get { return bitsPerSample; }                set { bitsPerSample = value; }            }        }        /// <summary>         /// fact块        /// </summary>         public class FactBlock        {            /// <summary>            /// 构造函数            /// </summary>            public FactBlock()            {                factId = new byte[4];            }            #region 字段、属性            private byte[] factId;            /// <summary>             /// 文件前四个字节 为fact             /// </summary>             public byte[] FactID            {                get { return factId; }                set { factId = value; }            }            private uint size;            /// <summary>             /// 数据大小             /// </summary>             public uint Size            {                get { return size; }                set { size = value; }            }            #endregion        }        /// <summary>        /// data块        /// </summary>         public class DataBlock        {            /// <summary>            /// 构造函数            /// </summary>            public DataBlock()            {                DataID = new byte[4];            }            #region 字段、属性            private byte[] m_DataID;            /// <summary>             /// 文件前四个字节 为data            /// </summary>              public byte[] DataID            {                get { return m_DataID; }                set { m_DataID = value; }            }            private uint m_DataSize;            /// <summary>             /// 大小             /// </summary>             public uint DataSize            {                get { return m_DataSize; }                set { m_DataSize = value; }            }            private Int16[] m_Data;            /// <summary>            /// 数据            /// </summary>            public Int16[] DataArray            {                get { return m_Data; }                set { m_Data =http://www.mamicode.com/ value; }            }            private Byte[] byteDataArray;            /// <summary>            /// 数据            /// </summary>            public Byte[] ByteDataArray            {                get { return byteDataArray; }                set { byteDataArray = value; }            }            //public Int16 this[int pos]            //{            //    get { return m_Data[pos]; }            //    set { m_DataID = value; }            //}            private int m_NumSamples;            /// <summary>            /// 采样数            /// </summary>            public int NumSamples            {                get { return m_NumSamples; }                set { m_NumSamples = value; }            }            #endregion        }        #endregion    }    /// <summary>     /// 文件头 标识类    /// </summary>     public static class WaveMark    {        /// <summary>         /// 文件前四个字节 为RIFF         /// </summary>         public static byte[] szRiffID = new byte[] { 0x52, 0x49, 0x46, 0x46 };   // ‘R‘,‘I‘,‘F‘,‘F‘         /// <summary>         ///WAVE文件定义 为WAVE         /// </summary>         public static byte[] szRiffWaveID = new byte[] { 0x57, 0x41, 0x56, 0x45 }; // ‘W‘,‘A‘,‘V‘,‘E‘                /// <summary>         /// 固定为  是"fmt "字后一位为0x20          /// </summary>         public static byte[] szRiffFormat = new byte[] { 0x66, 0x6D, 0x74, 0x20 }; // fmt        /// <summary>         /// 文件前四个字节 为fact         /// </summary>         public static byte[] factID = new byte[] { 0x66, 0x61, 0x63, 0x74 };   // ‘f‘,‘a‘,‘c‘,‘t‘         /// <summary>         /// 文件前四个字节 为RIFF         /// </summary>         public static byte[] dataID = new byte[] { 0x64, 0x61, 0x74, 0x61 };   // ‘d‘,‘a‘,‘t‘,‘a‘     }    /// <summary>    /// 音频格式    /// </summary>    public enum EnumAudioType    {               /// <summary>        /// 未知格式        /// </summary>        UnKnown = 0,        /// <summary>        /// 8k U-law 单声道        /// </summary>        Ulaw8k1 = 1,        /// <summary>        /// 8k U-law 双声道        /// </summary>        Ulaw8k2 = 2,        /// <summary>        /// 8K A-law单声道        /// </summary>        Alaw8k1 = 3,        /// <summary>        /// 8K A-law双声道        /// </summary>        Alaw8k2 = 4,        /// <summary>        /// 16K A-law单声道        /// </summary>        Alaw16k1 = 5,        /// <summary>        /// 16K A-law双声道        /// </summary>        Alaw16k2 = 6,        /// <summary>        /// 8K 8bit PCM单声道        /// </summary>        Linear8k8bit1 = 7,        /// <summary>        /// 8K 8bit PCM双声道        /// </summary>        Linear8k8bit2 = 8,        /// <summary>        /// 8K 16bit PCM单声道        /// </summary>        Linear8k16bit1 = 9,        /// <summary>        /// 8K 16bit PCM双声道        /// </summary>        Linear8k16bit2 = 10,        /// <summary>        /// 16K 16bit PCM单声道        /// </summary>        Linear16k16bit1 = 11,        /// <summary>        /// 16K 16bit PCM双声道        /// </summary>        Linear16k16bit2 = 12,        /// <summary>        /// 16K 8bit PCM单声道        /// </summary>        Linear16k8bit1 = 13,        /// <summary>        /// 16K 8bit PCM双声道        /// </summary>        Linear16k8bit2 = 14,        /// <summary>        /// 16k U-law 单声道        /// </summary>        Ulaw16k1 = 15,        /// <summary>        /// 16k U-law 双声道        /// </summary>        Ulaw16k2 = 16    }

 

Wav文件操作类