Python:将WAV文件写入NumPy浮点数组

20
ifile = wave.open("input.wav")

现在我该如何将这个文件写成一个numpy浮点数数组呢?


@JoranBeasley 它必须是浮点数。 - IAM
4个回答

42

谢谢!还有一个问题,我如何对当前工作目录中的所有.wav文件执行此操作?我的意思是在循环中将每个文件保存到一个数组中,并在每个步骤结束时将其集中到主数组中。 - IAM

23

这个问题被提出七年后...

import wave
import numpy

# Read file to get buffer                                                                                               
ifile = wave.open("input.wav")
samples = ifile.getnframes()
audio = ifile.readframes(samples)

# Convert buffer to float32 using NumPy                                                                                 
audio_as_np_int16 = numpy.frombuffer(audio, dtype=numpy.int16)
audio_as_np_float32 = audio_as_np_int16.astype(numpy.float32)

# Normalise float32 array so that values are between -1.0 and +1.0                                                      
max_int16 = 2**15
audio_normalised = audio_as_np_float32 / max_int16

3
你尝试过了吗?根据文档,自至少Python 2.7版本以来,wave模块就已是Python的一部分,并且在3.8版本中仍然包含:https://docs.python.org/3.8/library/wave.html - Matthew Walker
1
嗨,Matthew Walker,感谢您提供如此好的答案。我想问一下,audio_normalised 的大小是样本的两倍,那么它是否代表了2个通道的数据,还是其他什么,请您能详细解释一下吗? - Trees
我不确定我理解你的问题。你所说的大小是指字节长度吗?如果是这样,那么我猜测答案可能在于波形文件中PCM的int16(2字节)表示。这回答了你的问题吗? - Matthew Walker
哦,我认为wave.getsampwidthfrombufferint16int32的值,对吗? - avocado
1
@avocado getsampwidth() 返回样本宽度(以字节为单位),因此2个字节=> int16,或4个字节=> int32。我猜我之前没有遇到过除每个样本2个字节之外的WAV文件。好观点。 - Matthew Walker
显示剩余4条评论

9
使用librosa包,只需加载wav文件到numpy数组即可:
y, sr = librosa.load(filename)

加载并解码音频作为时间序列y,表示为一维NumPy浮点数组。变量sr包含y的采样率,即每秒音频样本数。默认情况下,所有音频在加载时都被混合为单声道,并重新采样为22050 Hz。可以通过向librosa.load()提供其他参数来覆盖此行为。
更多信息请参见Librosa库文档

0

我没有足够的声望在@Matthew Walker的回答下面进行评论,因此我发表了一个新答案,加入了对Matt答案的观察。 max_int16 应该是 2 ** 15-1 而不是 2 ** 15

更好的做法是,我认为应该用以下语句替换归一化行:

audio_normalised = audio_as_np_float32 / numpy.iinfo(numpy.int16).max

如果音频是立体声(即两个通道),左右值将交错存储。因此,为了获取立体声数组,可以使用以下方法:
channels = ifile.getnchannels()
audio_stereo = np.empty((int(len(audio_normalised)/channels), channels))
audio_stereo[:,0] = audio_normalised[range(0,len(audio_normalised),2)]
audio_stereo[:,1] = audio_normalised[range(1,len(audio_normalised),2)]

我相信这回答了评论区@Trees的问题。


关于max_int16的定义问题很有趣。 16位整数的范围为-32768到32767。 如果我们想要在-1到1之间进行缩放,则需要用绝对意义上最大可能值即32768或2 ** 15来除以。 因此,在我的答案中定义了max_int16 - Matthew Walker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接