Python Wave字节数据

jam*_*meh 6 python audio wave

我正在尝试从.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)
Run Code Online (Sandbox Code Playgroud)

这给出了:

b'\x00\x00\x00\x00'
Run Code Online (Sandbox Code Playgroud)

这是这首歌的"第一帧".这4个字节显然对应于每帧的(2个通道*2字节采样宽度)字节,但每个字节对应的是什么?

特别是,我试图将其转换为单声道振幅信号.

Wil*_*man 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
|_____|
Run Code Online (Sandbox Code Playgroud)

要转换为单声道,你可以做这样的事情,

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)
Run Code Online (Sandbox Code Playgroud)

从立体声到单声道都没有明确的方法.你可以放下一个频道.上面,我正在平均渠道.这一切都取决于您的应用程序.


Pau*_*aul 5

对于 wav 文件 IO,我更喜欢使用 scipy。读取 wav 文件可能有点大材小用,但通常在读取 wav 文件后,进行下游处理会更容易。

import scipy.io.wavfile
fs1, y1 = scipy.io.wavfile.read(filename)
Run Code Online (Sandbox Code Playgroud)

从这里开始,数据 y1 将有 N 个样本长,并且将有 Z 列,其中每列对应一个通道。要转换为单声道 wav 文件,您无需说明您希望如何进行转换。你可以取平均值,或者你想要的任何其他值。对于一般用途

monoChannel = y1.mean(axis=1)
Run Code Online (Sandbox Code Playgroud)