解析WAV文件头

3 投票
2 回答
6645 浏览
提问于 2025-04-16 07:13

我正在写一个程序,用来解析WAV文件的头部信息,并把这些信息打印到屏幕上。在写这个程序之前,我先做了一些研究。

我用命令查看了一个WAV文件的前48个字节:

hexdump -n 48 sound_file_8000hz.wav

00000000  52 49 46 46 bc af 01 00  57 41 56 45 66 6d 74 20    |RIFF....WAVEfmt |
00000010  10 00 00 00 01 00 01 00  >40 1f 00 00< 40 1f 00 00  |........@...@...|
00000020  01 00 08 00 64 61 74 61  98 af 01 00 81 80 81 80    |....data........|

然后又查看了另一个WAV文件:

hexdump -n 48 sound_file_44100hz.wav

00000000  52 49 46 46 c4 ea 1a 00  57 41 56 45 66 6d 74 20    |RIFF....WAVEfmt |
00000010  10 00 00 00 01 00 02 00  >44 ac 00 00< 10 b1 02 00  |........D.......|
00000020  04 00 10 00 64 61 74 61  a0 ea 1a 00 00 00 00 00    |....data........|

在这两个文件中,>和<之间的部分就是采样率。

那么“40 1f 00 00”是怎么变成8000Hz的,而“44 ac 00 00”又是怎么变成44100Hz的呢?像声道数量和音频格式这样的信息可以直接从这些数据中读取。我找到一个叫做WavHeader的Python脚本,它能正确解析这两个文件的采样率。这是脚本的核心部分:

 bufHeader = fileIn.read(38)
    # Verify that the correct identifiers are present
    if (bufHeader[0:4] != "RIFF") or \
       (bufHeader[12:16] != "fmt "): 
         logging.debug("Input file not a standard WAV file")
         return
    # endif
    stHeaderFields = {'ChunkSize' : 0, 'Format' : '',
        'Subchunk1Size' : 0, 'AudioFormat' : 0,
        'NumChannels' : 0, 'SampleRate' : 0,
        'ByteRate' : 0, 'BlockAlign' : 0,
        'BitsPerSample' : 0, 'Filename': ''}
    # Parse fields
    stHeaderFields['ChunkSize'] = struct.unpack('<L', bufHeader[4:8])[0]
    stHeaderFields['Format'] = bufHeader[8:12]
    stHeaderFields['Subchunk1Size'] = struct.unpack('<L', bufHeader[16:20])[0]
    stHeaderFields['AudioFormat'] = struct.unpack('<H', bufHeader[20:22])[0]
    stHeaderFields['NumChannels'] = struct.unpack('<H', bufHeader[22:24])[0]
    stHeaderFields['SampleRate'] = struct.unpack('<L', bufHeader[24:28])[0]
    stHeaderFields['ByteRate'] = struct.unpack('<L', bufHeader[28:32])[0]
    stHeaderFields['BlockAlign'] = struct.unpack('<H', bufHeader[32:34])[0]
    stHeaderFields['BitsPerSample'] = struct.unpack('<H', bufHeader[34:36])[0]

我不明白为什么这个脚本能提取出正确的采样率,而我用hexdump却不能。

我使用的WAV文件格式的信息来自这个页面:

https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

2 个回答

5

它们是 小端序

>>> 0x00001f40
8000
>>> 0x0000ac44
44100
8

这段“40 1F 00 00”的字节代表一个整数,它的十六进制值是00001F40(记住,在WAVE文件中,整数是以小端格式存储的)。十六进制的00001F40转换成十进制就是8000。

同样,“44 AC 00 00”的字节也代表一个整数,它的十六进制值是0000AC44。十六进制的0000AC44转换成十进制就是44100。

撰写回答