WAVE(.wav)檔案遵循 RIFF 容器格式,標頭包含音訊格式、取樣率、聲道數、位深度等關鍵資訊。本文提供完整 C# 程式碼,解析前 44 位元組標頭,使用 BinaryReader/BitConverter 處理小端序資料。
| 偏移 | 大小 | 欄位 | 說明 | 範例值 |
|---|---|---|---|---|
| 0 | 4 | ChunkID | "RIFF" 標識 | 0x52494646 |
| 4 | 4 | ChunkSize | 檔案大小 - 8 | 小端序整數 |
| 8 | 4 | Format | "WAVE" | 0x57415645 |
| 12 | 4 | Subchunk1ID | "fmt " | 0x666D7420 |
| 16 | 4 | Subchunk1Size | PCM 固定 16 | 16 |
| 20 | 2 | AudioFormat | 1=PCM, 其他=壓縮 | 1 |
| 22 | 2 | NumChannels | 1=單聲道, 2=立體聲 | 2 |
| 24 | 4 | SampleRate | 取樣率 (Hz) | 44100 |
| 28 | 4 | ByteRate | SampleRate × NumChannels × BitsPerSample/8 | 176400 |
| 32 | 2 | BlockAlign | NumChannels × BitsPerSample/8 | 4 |
| 34 | 2 | BitsPerSample | 位深度 (8/16/24/32) | 16 |
| 36 | 4 | Subchunk2ID | "data" | 0x64617461 |
| 40 | 4 | Subchunk2Size | 音訊資料大小 | ... |
using System;
using System.IO;
public struct WavInfo
{
public string ChunkID; // "RIFF"
public uint ChunkSize; // 檔案大小 - 8
public string Format; // "WAVE"
public string Subchunk1ID; // "fmt "
public uint Subchunk1Size; // 16 for PCM
public ushort AudioFormat; // 1 = PCM
public ushort NumChannels; // 聲道數
public uint SampleRate; // 取樣率
public uint ByteRate; // 位元率
public ushort BlockAlign; // 區塊對齊
public ushort BitsPerSample; // 位深度
public string Subchunk2ID; // "data"
public uint Subchunk2Size; // 資料大小
}
public static class WavHeaderReader
{
public static WavInfo Read(string filePath)
{
if (!File.Exists(filePath))
throw new FileNotFoundException("找不到檔案", filePath);
var info = new WavInfo();
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
if (fs.Length < 44)
throw new InvalidDataException("檔案太小,非有效 WAVE 檔案");
byte[] header = new byte[44];
fs.Read(header, 0, 44);
// 使用 BitConverter 處理小端序(Little Endian)
info.ChunkID = System.Text.Encoding.ASCII.GetString(header, 0, 4);
info.ChunkSize = BitConverter.ToUInt32(header, 4);
info.Format = System.Text.Encoding.ASCII.GetString(header, 8, 4);
info.Subchunk1ID = System.Text.Encoding.ASCII.GetString(header, 12, 4);
info.Subchunk1Size = BitConverter.ToUInt32(header, 16);
info.AudioFormat = BitConverter.ToUInt16(header, 20);
info.NumChannels = BitConverter.ToUInt16(header, 22);
info.SampleRate = BitConverter.ToUInt32(header, 24);
info.ByteRate = BitConverter.ToUInt32(header, 28);
info.BlockAlign = BitConverter.ToUInt16(header, 32);
info.BitsPerSample = BitConverter.ToUInt16(header, 34);
info.Subchunk2ID = System.Text.Encoding.ASCII.GetString(header, 36, 4);
info.Subchunk2Size = BitConverter.ToUInt32(header, 40);
// 驗證關鍵標識
if (info.ChunkID != "RIFF" || info.Format != "WAVE" || info.Subchunk1ID != "fmt ")
throw new InvalidDataException("非標準 WAVE 檔案格式");
}
return info;
}
public static void PrintInfo(WavInfo info)
{
Console.WriteLine($"ChunkID: {info.ChunkID}");
Console.WriteLine($"ChunkSize: {info.ChunkSize} bytes");
Console.WriteLine($"Format: {info.Format}");
Console.WriteLine($"Subchunk1ID: {info.Subchunk1ID}");
Console.WriteLine($"Subchunk1Size: {info.Subchunk1Size}");
Console.WriteLine($"AudioFormat: {info.AudioFormat} (1=PCM)");
Console.WriteLine($"NumChannels: {info.NumChannels}");
Console.WriteLine($"SampleRate: {info.SampleRate} Hz");
Console.WriteLine($"ByteRate: {info.ByteRate} bytes/sec");
Console.WriteLine($"BlockAlign: {info.BlockAlign}");
Console.WriteLine($"BitsPerSample: {info.BitsPerSample} bits");
Console.WriteLine($"Subchunk2ID: {info.Subchunk2ID}");
Console.WriteLine($"Subchunk2Size: {info.Subchunk2Size} bytes");
// 衍生資訊
double duration = (double)info.Subchunk2Size / info.ByteRate;
Console.WriteLine($"Duration: {duration:F2} seconds");
}
}
static void Main(string[] args)
{
string path = args.Length > 0 ? args[0] : @"C:\Test\audio.wav";
try
{
var info = WavHeaderReader.Read(path);
WavHeaderReader.PrintInfo(info);
}
catch (Exception ex)
{
Console.WriteLine($"錯誤: {ex.Message}");
}
}
WAVE 檔案採用 Little Endian(低位元組在前)。BitConverter 在 Windows (x86/x64) 上預設即為小端序,直接對應:
ToUInt16:2 位元組 → ushortToUInt32:4 位元組 → uintToInt16/ToInt32:有號版本RIFF 標識為 ASCII 字串,用 Encoding.ASCII.GetString(bytes, offset, count) 解析。
檢查 RIFF、WAVE、fmt 三大標識,快速排除非 WAVE 檔案。
ChunkSize 為 uint,>4GB 需 RIFF64 (RF64) 格式AudioFormat 判斷 PCM/IEEE Float/ADPCM/MP3 等BinaryReader 逐段讀取WavInfo 設計為不可變結構WAVE 標頭解析核心在於:
BitConverter 處理小端序整數轉換WavInfo 供上層應用使用本程式碼可直接整合至音訊處理、轉檔、播放器等專案中。