[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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM