首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 解析 WAV 檔案標頭:BinaryReader 讀取 RIFF/WAVE/fmt/data Chunk 結構

     編輯:關於C#

WAV 檔案格式簡介

WAV (Waveform Audio File Format) 採用 RIFF 容器結構,由多個 Chunk 組成:


RIFF Header (12 bytes)
  "RIFF" (4) | FileSize-8 (4) | "WAVE" (4)

fmt Chunk (24 bytes for PCM)
  "fmt " (4) | ChunkSize(4)=16 | AudioFormat(2) | Channels(2)
  SampleRate(4) | ByteRate(4) | BlockAlign(2) | BitsPerSample(2)

data Chunk
  "data" (4) | DataSize (4) | 波形資料...

結構體定義


public struct WavHeader
{
    // RIFF Header
    public string RiffId;        // "RIFF"
    public int FileSize;         // 總檔案大小 - 8
    public string WaveId;        // "WAVE"

    // fmt Chunk
    public string FmtId;         // "fmt "
    public int FmtSize;          // 16 for PCM
    public short AudioFormat;    // 1 = PCM
    public short Channels;       // 1=單聲道, 2=立體聲
    public int SampleRate;       // 8000, 44100, 48000...
    public int ByteRate;         // SampleRate * Channels * BitsPerSample/8
    public short BlockAlign;     // Channels * BitsPerSample/8
    public short BitsPerSample;  // 8, 16, 24, 32

    // data Chunk
    public string DataId;        // "data"
    public int DataSize;         // 波形資料大小
}

BinaryReader 讀取實作


public static WavHeader ReadWavHeader(string filePath)
{
    var header = new WavHeader();
    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    using (var br = new BinaryReader(fs))
    {
        // RIFF Header
        header.RiffId = new string(br.ReadChars(4));
        if (header.RiffId != "RIFF") throw new InvalidDataException("非 RIFF 檔案");

        header.FileSize = br.ReadInt32();
        header.WaveId = new string(br.ReadChars(4));
        if (header.WaveId != "WAVE") throw new InvalidDataException("非 WAVE 格式");

        // 尋找 fmt chunk (可能中間有其他 chunk)
        while (fs.Position < fs.Length)
        {
            string chunkId = new string(br.ReadChars(4));
            int chunkSize = br.ReadInt32();

            if (chunkId == "fmt ")
            {
                header.FmtId = chunkId;
                header.FmtSize = chunkSize;
                header.AudioFormat = br.ReadInt16();
                header.Channels = br.ReadInt16();
                header.SampleRate = br.ReadInt32();
                header.ByteRate = br.ReadInt32();
                header.BlockAlign = br.ReadInt16();
                header.BitsPerSample = br.ReadInt16();

                // 若 fmt size > 16,略過擴充資料
                if (chunkSize > 16) fs.Seek(chunkSize - 16, SeekOrigin.Current);
            }
            else if (chunkId == "data")
            {
                header.DataId = chunkId;
                header.DataSize = chunkSize;
                break; // 找到 data chunk,後續即為波形資料
            }
            else
            {
                // 略過未知 chunk
                fs.Seek(chunkSize, SeekOrigin.Current);
            }
        }
    }
    return header;
}

關鍵技術點

應用範例:計算音訊長度


var h = ReadWavHeader("test.wav");
double durationSec = (double)h.DataSize / h.ByteRate;
Console.WriteLine($"長度: {durationSec:F2} 秒");
Console.WriteLine($"格式: {h.Channels}ch, {h.SampleRate}Hz, {h.BitsPerSample}bit");

擴充:支援更多格式

  • 浮點 PCM:AudioFormat = 3 (IEEE Float)
  • 擴充 fmt:FmtSize = 40 包含 cbSize、wValidBitsPerSample、dwChannelMask、SubFormat (GUID)
  • LIST/INFO chunk:中繼資料 (標題、藝術家、版權等)
  • RF64 / BWF:大檔案 (>4GB) 擴充格式

總結

WAV 標頭解析是音訊處理基礎。掌握 RIFF Chunk 架構、BinaryReader 讀取、位置控制與驗證邏輯,即可建立健壯的音訊檔案分析工具,進階可整合 NAudio 等庫進行解碼、轉檔、視覺化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
技術說明
BinaryReader直接讀取基本型別 (ReadInt32, ReadInt16, ReadChars),自動處理 Little-Endian
Chunk 遍歷RIFF 允許任意順序 chunk,必須迴圈尋找 "fmt " 與 "data"
位置控制fs.Seek 跳過未知/擴充 chunk
驗證檢查 "RIFF"、"WAVE"、"fmt "、"data" 四個標識