You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请教WAV文件16位数据段的存储格式及解析方法

16位WAV音频数据解析方案

核心原理

WAV文件中的16位音频数据是以小端字节序的有符号短整数存储的:

  • 每个采样占2个连续字节,低字节在前、高字节在后
  • 数值范围为 -32768 到 32767,对应音频振幅(0为静音,正负对应波形的上下摆动)
  • 单声道文件的采样连续排列;立体声则遵循左声道、右声道交替排列的规则(你的440Hz测试文件如果是单声道,直接按2字节一组解析即可)

代码修正与实现

你的现有代码完成了头文件验证,但在音频数据读取环节未按16位单元处理,同时存在部分逻辑错误,以下是修正后的完整代码:

## CHECK FILE VALIDITY ##
# Import required libraries
import sys
import struct  # 用标准库处理二进制数据更可靠

# Open the file
fileName = sys.argv[1]
with open(fileName, 'rb') as f:
    data = f.read()

# Check RIFF header
if data[:4] != b'RIFF':
    raise FileExistsError('Invalid RIFF header')
# 验证PCM格式的WAV头(fmt块大小固定为16)
if data[8:24] != b'WAVEfmt \x10\x00\x00\x00':
    raise FileExistsError('Invalid WAV format (only PCM 16-bit supported)')

## GET AND PRINT FILE INFO ##
# Calculate total file size
riff_chunk_size = struct.unpack('<I', data[4:8])[0]
file_length = riff_chunk_size + 8  # RIFF大小不含自身8字节,需补全
print('\nFile Size:')
if file_length < 1024 * 1024:
    print(f"{round(file_length / 1024, 1)}K")
elif file_length < 1024 * 1024 * 1024:
    print(f"{round(file_length / (1024*1024), 2)}M")
else:
    raise NotImplementedError('File too large, gigabyte size not implemented')

# Get sample rate
sampleRate = struct.unpack('<I', data[24:28])[0]
print(f'\nSample Rate:\n{sampleRate}Hz')

# Get bits per sample
bitsPerSample = struct.unpack('<H', data[34:36])[0]
print(f'\nBits per Sample:\n{bitsPerSample} Bits')
if bitsPerSample != 16:
    raise ValueError('Unsupported or invalid Bits per Sample')

# Find data chunk (跳过所有非data子块,兼容带额外块的WAV文件)
data_start = 0
offset = 12  # 跳过RIFF、WAVE标识,从第一个子块开始遍历
while offset < len(data):
    chunk_id = data[offset:offset+4]
    chunk_size = struct.unpack('<I', data[offset+4:offset+8])[0]
    if chunk_id == b'data':
        data_start = offset + 8
        data_length = chunk_size
        break
    offset += 8 + chunk_size  # 移动到下一个子块
else:
    raise FileNotFoundError('No data chunk found in WAV file')

print(f'\nData starts at offset {data_start}')
print('\nParsing 16-bit audio data...')

# 解析16位音频采样
audio_samples = []
# 按2字节一组读取,转换为小端有符号短整型
for i in range(0, data_length, 2):
    sample = struct.unpack('<h', data[data_start + i : data_start + i + 2])[0]
    audio_samples.append(sample)

# 输出前10个采样验证(440Hz正弦波会呈现规律的正负交替数值)
print('\nFirst 10 audio samples:')
print(audio_samples[:10])

关键修改说明

  1. 用struct库简化二进制处理:struct是Python处理二进制数据的标准工具,<h表示小端有符号短整型,<I表示小端无符号整型,比手动反转字节更高效可靠。
  2. 健壮查找data块:WAV文件可能包含额外子块(如LIST信息块),循环遍历子块查找data标识的方式,比硬编码或逐个字节判断更兼容不同格式的WAV文件。
  3. 正确解析16位采样:每次读取2字节并转换为有符号短整数,得到的数值直接对应音频的振幅强度。
  4. 修正文件长度计算:RIFF块的大小字段不包含自身的8字节,因此总文件大小需要补加该部分长度。

内容的提问来源于stack exchange,提问作者Donovan Black

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:17:01