解析WAV数据
我正在尝试写一个程序来显示PCM数据。为了找到合适的库,我感到非常沮丧,但我找到了Python的wave库,并开始使用它。不过,我不太确定该如何解读这些数据。
wave.getparams函数返回的信息是(2个声道,2个字节,44100赫兹,96333帧,未压缩,未压缩)。这些信息看起来都不错,但当我尝试打印一个单独的帧时,得到了'\xc0\xff\xd0\xff',这总共是4个字节。我想可能一帧包含2个样本,但问题并不止于此。
96333帧 * 2样本/帧 * (1/44.1k秒/样本) = 4.3688秒
然而,iTunes显示的时间更接近2秒,而根据文件大小和比特率的计算结果大约是2.7秒。这到底是怎么回事呢?
另外,我怎么知道这些字节是有符号的还是无符号的呢?
非常感谢!
6 个回答
4
我知道已经有人接受了答案,但我之前做过一些音频相关的事情,你需要像这样解压波形文件。
pcmdata = wave.struct.unpack("%dh"%(wavedatalength),wavedata)
另外,我用过一个叫做PyAudio的库,不过我还是需要和它一起使用wave这个库。
21
谢谢你的帮助!我已经搞定了这个问题,我会把解决方案发在这里,方便其他遇到同样问题的人使用:
import wave
import struct
def pcm_channels(wave_file):
"""Given a file-like object or file path representing a wave file,
decompose it into its constituent PCM data streams.
Input: A file like object or file path
Output: A list of lists of integers representing the PCM coded data stream channels
and the sample rate of the channels (mixed rate channels not supported)
"""
stream = wave.open(wave_file,"rb")
num_channels = stream.getnchannels()
sample_rate = stream.getframerate()
sample_width = stream.getsampwidth()
num_frames = stream.getnframes()
raw_data = stream.readframes( num_frames ) # Returns byte data
stream.close()
total_samples = num_frames * num_channels
if sample_width == 1:
fmt = "%iB" % total_samples # read unsigned chars
elif sample_width == 2:
fmt = "%ih" % total_samples # read signed 2 byte shorts
else:
raise ValueError("Only supports 8 and 16 bit audio formats.")
integer_data = struct.unpack(fmt, raw_data)
del raw_data # Keep memory tidy (who knows how big it might be)
channels = [ [] for time in range(num_channels) ]
for index, value in enumerate(integer_data):
bucket = index % num_channels
channels[bucket].append(value)
return channels, sample_rate
10
“两个通道”就是立体声,所以把每个通道的时长相加是没有意义的——这样算出来的时间会多一倍(应该是2.18秒,而不是4.37秒)。至于有符号和无符号的区别,像这里所解释的,我引用一下:
8位的音频样本是以无符号字节的形式存储,范围是0到255。而16位的样本则是以2的补码形式存储的有符号整数,范围是-32768到32767。
这部分内容是WAV格式的规范(实际上是它的超集RIFF的一部分),所以和你使用哪个库来处理WAV文件没有关系。