zoukankan      html  css  js  c++  java
  • [VB.NET][C#]WAV格式文件头部解析

    简介

      WAV 为微软开发的一种声音文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源。

    第一节 文件头部格式

      文件头(Header)是位于文件开头的一段承担一定任务的数据,通常是对主体数据的描述。

      WAV 文件头由哪几部分构成

      RIFF块(RIFF-Chunk)

      格式化块(Format-Chunk)

      附加块(Fact-Chunk)块偏移地址需要根据实际数据变更

      数据块(Data-Chunk)块偏移地址需要根据实际数据变更

    偏移地址 字节数 数据类型 内容
    &H00 4 String 'RIFF'文件标志
    &H04 4 UInteger 文件总长
    &H08  4  String  'WAVE'文件标志

    表1-1 RIFF块(RIFF-Chunk)

    偏移地址 字节数 数据类型 内容
    &H0C 4 String 'fmt'标志
    &H10 4 UInteger 块长度
    &H12  2  UShort PCM格式类别 
    &H14 2 UShort 声道数目 
    &H18 4 UInteger 采样率 
    &H1C 4 UInteger 传输速率 
    &H1E 2 UShort 数据块对齐 
    &H20 2 UShort 每样本bit数 
    &H22 2 UShort 可选

    表1-2 格式化块(Format-Chunk)

    偏移地址 字节数 数据类型 内容
    &H26 4 String 'fact'标志
    &H2A 4 UInteger 块长度
    &H2E 4 UInteger 附加信息

    表1-3 附加块(Fact-Chunk)

    偏移地址 字节数 数据类型 内容
    &H32 4 String 'data'文件标志
    &H36 4 UInteger 数据块总长

    表1-4 数据块(Data-Chunk)

    第二节 代码实现

      1. 构建一个 WaveHeader 结构体

    ''' <summary>
    ''' wav音频头部信息
    ''' </summary>
    Public Structure WaveHeader
    #Region "RiffChunk"
        ''' <summary>
        ''' RIFF标志
        ''' </summary>
        Dim RIFF As String
        ''' <summary>
        ''' 文件长度
        ''' </summary>
        Dim FileSize As UInteger
        ''' <summary>
        ''' WAVE标志
        ''' </summary>
        Dim WAVE As String
    #End Region
    #Region "FormatChunk"
        ''' <summary>
        ''' FORMAT标志
        ''' </summary>
        Dim FORMAT As String
        ''' <summary>
        ''' Format长度
        ''' </summary>
        Dim FormatSize As UInteger
        ''' <summary>
        ''' 编码方式
        ''' </summary>
        Dim FilePadding As UShort
        ''' <summary>
        ''' 声道数目
        ''' </summary>
        Dim FormatChannels As UShort
        ''' <summary>
        ''' 采样频率
        ''' </summary>
        Dim SamplesPerSecond As UInteger
        ''' <summary>
        ''' 每秒所需字节数
        ''' </summary>
        Dim AverageBytesPerSecond As UInteger
        ''' <summary>
        ''' 数据块对齐单位
        ''' </summary>
        Dim BytesPerSample As UShort
        ''' <summary>
        ''' 单个采样所需Bit数
        ''' </summary>
        Dim BitsPerSample As UShort
        ''' <summary>
        ''' 附加信息
        ''' </summary>
        Dim FormatExtra As UShort
    #End Region
    #Region "FactChunk"
        ''' <summary>
        ''' FACT标志
        ''' </summary>
        Dim FACT As String
        ''' <summary>
        ''' Fact长度
        ''' </summary>
        Dim FactSize As UInteger
        ''' <summary>
        ''' Fact信息
        ''' </summary>
        Dim FactInf As UInteger
    #End Region
    #Region "DataChunk"
        ''' <summary>
        ''' DATA标志
        ''' </summary>
        Dim DATA As String
        ''' <summary>
        ''' Data长度
        ''' </summary>
        Dim DataSize As UInteger
    #End Region
    End Structure
    VB.NET-WaveHeader
    /// <summary>
    /// wav音频头部信息
    /// </summary>
    public struct WaveHeader
    {
        #region "RiffChunk"
        /// <summary>
        /// RIFF标志
        /// </summary>
        public string RIFF;
        /// <summary>
        /// 文件长度
        /// </summary>
        public uint FileSize;
        /// <summary>
        /// WAVE标志
        /// </summary>
            #endregion
        public string WAVE;
        #region "FormatChunk"
        /// <summary>
        /// FORMAT标志
        /// </summary>
        public string FORMAT;
        /// <summary>
        /// Format长度
        /// </summary>
        public uint FormatSize;
        /// <summary>
        /// 编码方式
        /// </summary>
        public ushort FilePadding;
        /// <summary>
        /// 声道数目
        /// </summary>
        public ushort FormatChannels;
        /// <summary>
        /// 采样频率
        /// </summary>
        public uint SamplesPerSecond;
        /// <summary>
        /// 每秒所需字节数
        /// </summary>
        public uint AverageBytesPerSecond;
        /// <summary>
        /// 数据块对齐单位
        /// </summary>
        public ushort BytesPerSample;
        /// <summary>
        /// 单个采样所需Bit数
        /// </summary>
        public ushort BitsPerSample;
        /// <summary>
        /// 附加信息
        /// </summary>
            #endregion
        public ushort FormatExtra;
        #region "FactChunk"
        /// <summary>
        /// FACT标志
        /// </summary>
        public string FACT;
        /// <summary>
        /// Fact长度
        /// </summary>
        public uint FactSize;
        /// <summary>
        /// Fact信息
        /// </summary>
            #endregion
        public uint FactInf;
        #region "DataChunk"
        /// <summary>
        /// DATA标志
        /// </summary>
        public string DATA;
        /// <summary>
        /// Data长度
        /// </summary>
            #endregion
        public uint DataSize;
    }
    C#-WaveHeader

      2. 打开 *.wav 二进制文件

      Dim data() As Byte = My.Computer.FileSystem.ReadAllBytes(wavFileName) 
    VB.NET-OpenFile
        byte[] data = System.IO.File.ReadAllBytes(wavFileName);
    C#-OpenFile

      3. 文件头部信息解析

        ''' <summary>
        ''' 返回指定字节数组包含的Wave头部信息
        ''' </summary>
        Public Function GetWaveHeaderFromBytes(data As Byte()) As WaveHeader
            Dim header As New WaveHeader
            Dim tempIndex As UShort = 0
            header.RIFF = CType(System.Text.Encoding.ASCII.GetChars(data, 0, 4), String)
            header.FileSize = System.BitConverter.ToUInt32(data, 4)
            header.WAVE = CType(System.Text.Encoding.ASCII.GetChars(data, 8, 4), String)
            'FormatChunk
            header.FORMAT = CType(System.Text.Encoding.ASCII.GetChars(data, 12, 4), String)
            header.FormatSize = System.BitConverter.ToUInt32(data, 16)
            header.FilePadding = System.BitConverter.ToUInt16(data, 20)
            header.FormatChannels = System.BitConverter.ToUInt16(data, 22)
            header.SamplesPerSecond = System.BitConverter.ToUInt32(data, 24)
            header.AverageBytesPerSecond = System.BitConverter.ToUInt32(data, 28)
            header.BytesPerSample = System.BitConverter.ToUInt16(data, 32)
            header.BitsPerSample = System.BitConverter.ToUInt16(data, 34)
            If header.FormatSize = 18 Then
                header.FormatExtra = System.BitConverter.ToUInt16(data, 36)
            Else
                header.FormatExtra = 0
            End If
            tempIndex = 20 + header.FormatSize
            'FactChunk
            header.FACT = CType(System.Text.Encoding.ASCII.GetChars(data, tempIndex, 4), String)
            If header.FACT = "fact" Then
                header.FactSize = System.BitConverter.ToUInt32(data, tempIndex + 4)
                header.FactInf = IIf(header.FactSize = 2, System.BitConverter.ToUInt16(data, tempIndex + 8), System.BitConverter.ToUInt32(data, tempIndex + 8))
                tempIndex = tempIndex + header.FactSize + 8
            Else
                header.FACT = "NULL"
                header.FactSize = 0
                header.FactInf = 0
            End If
            'DataChunk
            header.DATA = CType(System.Text.Encoding.ASCII.GetChars(data, tempIndex, 4), String)
            header.DataSize = System.BitConverter.ToUInt32(data, tempIndex + 4)
            Return header
        End Function
    VB.NET-GetWaveHeaderFromBytes
    /// <summary>
    /// 返回指定字节数组包含的Wave头部信息
    /// </summary>
    public WaveHeader GetWaveHeaderFromBytes(byte[] data)
    {
        WaveHeader header = new WaveHeader();
        ushort tempIndex = 0;
        header.RIFF = Convert.ToString(System.Text.Encoding.ASCII.GetChars(data, 0, 4));
        header.FileSize = System.BitConverter.ToUInt32(data, 4);
        header.WAVE = Convert.ToString(System.Text.Encoding.ASCII.GetChars(data, 8, 4));
        //FormatChunk
        header.FORMAT = Convert.ToString(System.Text.Encoding.ASCII.GetChars(data, 12, 4));
        header.FormatSize = System.BitConverter.ToUInt32(data, 16);
        header.FilePadding = System.BitConverter.ToUInt16(data, 20);
        header.FormatChannels = System.BitConverter.ToUInt16(data, 22);
        header.SamplesPerSecond = System.BitConverter.ToUInt32(data, 24);
        header.AverageBytesPerSecond = System.BitConverter.ToUInt32(data, 28);
        header.BytesPerSample = System.BitConverter.ToUInt16(data, 32);
        header.BitsPerSample = System.BitConverter.ToUInt16(data, 34);
        if (header.FormatSize == 18) {
            header.FormatExtra = System.BitConverter.ToUInt16(data, 36);
        } else {
            header.FormatExtra = 0;
        }
        tempIndex = 20 + header.FormatSize;
        //FactChunk
        header.FACT = Convert.ToString(System.Text.Encoding.ASCII.GetChars(data, tempIndex, 4));
        if (header.FACT == "fact") {
            header.FactSize = System.BitConverter.ToUInt32(data, tempIndex + 4);
            header.FactInf = (header.FactSize == 2 ? System.BitConverter.ToUInt16(data, tempIndex + 8) : System.BitConverter.ToUInt32(data, tempIndex + 8));
            tempIndex = tempIndex + header.FactSize + 8;
        } else {
            header.FACT = "NULL";
            header.FactSize = 0;
            header.FactInf = 0;
        }
        //DataChunk
        header.DATA = Convert.ToString(System.Text.Encoding.ASCII.GetChars(data, tempIndex, 4));
        header.DataSize = System.BitConverter.ToUInt32(data, tempIndex + 4);
        return header;
    }
    C#-GetWaveHeaderFromBytes

    附录

      SoundPlayer 类 - MSDN

  • 相关阅读:
    Linux中批量添加文件和修改文件小笔记
    scp 命令快速使用讲解
    使用Apache Spark 对 mysql 调优 查询速度提升10倍以上
    阿里云CentOS-7.2安装mysql
    yum安装网络配置图形界面
    忘记了root密码,如何进入系统?
    Linux学习之竿头直上
    Linux命令之初出茅庐
    Linux学习之要点必备
    阿里云CentOS7.2服务器的安装
  • 原文地址:https://www.cnblogs.com/experdot/p/4396980.html
Copyright © 2011-2022 走看看