我正在尝试从.wav文件中读取数据。
import wave
wr = wave.open("~/01 Road.wav", 'r')
# sample width is 2 bytes
# number of channels is 2
wave_data = wr.readframes(1)
print(wave_data)
这给出了:
b'\x00\x00\x00\x00'
这首歌的“第一帧”。这4个字节显然对应于每帧的(2个通道* 2字节采样宽度)字节,但每个字节对应的是什么?
特别是,我试图将其转换为单声道振幅信号。
答案 0 :(得分:16)
如果您想了解“框架”是什么,则必须阅读波形文件格式的标准。例如:https://web.archive.org/web/20140221054954/http://home.roadrunner.com/~jgglatt/tech/wave.htm
从该文件:
意图“播放”的样本点,即同时发送到数模转换器(DAC)的样本点统称为样本帧。在我们的立体声波形示例中,每两个采样点构成另一个采样帧。下面针对该立体声示例进行了说明。
sample sample sample
frame 0 frame 1 frame N
_____ _____ _____ _____ _____ _____
| ch1 | ch2 | ch1 | ch2 | . . . | ch1 | ch2 |
|_____|_____|_____|_____| |_____|_____|
_____
| | = one sample point
|_____|
要转换为单声道,你可以做这样的事情,
import wave
def stereo_to_mono(hex1, hex2):
"""average two hex string samples"""
return hex((ord(hex1) + ord(hex2))/2)
wr = wave.open('piano2.wav','r')
nchannels, sampwidth, framerate, nframes, comptype, compname = wr.getparams()
ww = wave.open('piano_mono.wav','wb')
ww.setparams((1,sampwidth,framerate,nframes,comptype,compname))
frames = wr.readframes(wr.getnframes()-1)
new_frames = ''
for (s1, s2) in zip(frames[0::2],frames[1::2]):
new_frames += stereo_to_mono(s1,s2)[2:].zfill(2).decode('hex')
ww.writeframes(new_frames)
从立体声到单声道没有明确的方法。你可以放下一个频道。上面,我正在平均渠道。这一切都取决于你的申请。
答案 1 :(得分:3)
对于wav文件IO,我更喜欢使用scipy。读取wav文件可能有点过分,但通常在阅读wav后,下游处理更容易。
import scipy.io.wavfile
fs1, y1 = scipy.io.wavfile.read(filename)
从这里数据y1将是N个样本长,并且将具有Z列,其中每列对应于一个通道。要转换为单声道wav文件,您不会说您希望如何进行转换。您可以采取平均值,或其他任何你想要的。平均使用
monoChannel = y1.mean(axis=1)
答案 2 :(得分:2)
作为您问题的直接答案:两个字节以“通常”方式生成一个16位整数值,由显式公式value = ord(data[0]) + 256 * ord(data[1])
给出。但是使用struct
模块是解码(以后重新编码)这种多字节整数的更好方法:
import struct
print(struct.unpack("HH", b"\x00\x00\x00\x00"))
# -> gives a 2-tuple of integers, here (0, 0)
或者,如果我们想要一个签名的 16位整数(我认为是.wav文件中的情况),请使用"hh"
而不是"HH"
。 (我告诉你的任务是确定两个字节究竟如何编码从-32768到32767的整数值: - )
答案 3 :(得分:0)
将2个字节转换为int16的另一种方法是使用numpy.fromstring()。这是一个例子: audio_sample来自wav文件。
>>> audio_sample[0:8]
b'\x8b\xff\xe1\xff\x92\xffn\xff'
>>> x = np.fromstring(audio_sample, np.int16)
>>> x[0:4]
array([-117, -31, -110, -146], dtype=int16)
您可以使用np.tobytes转换回字节