scipy.io:无法写入wav文件

9
我遇到了一个问题,需要将一个2D的numpy数组写成一个波形文件(音频)。
根据文档,我应该写入一个2D的int16 numpy数组。

https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.io.wavfile.write.html

16-bit PCM  -32768  +32767  int16

我的numpy数组取值范围为(-1, 1),格式为float32,因此首先将其转换为16位整数

stereoAudio = ((stereoAudio * bits16max)).astype('int16')

print "argmax : " + str(np.amax(stereoAudio))
print "argmin : " + str(np.amin(stereoAudio))

outWaveFileName = "out/file.wav"
print "writing " + outWaveFileName
wavfile.write(outWaveFileName,44100,stereoAudio)

我得到以下输出:
argmax : 4389
argmin : -4381
writing out/file.wav
Traceback (most recent call last):
  File "/Users/me/file.py", line 132, in <module>
wavfile.write(outWaveFileName,44100,stereoAudio)
  File "//anaconda/lib/python2.7/site-packages/scipy/io/wavfile.py", line 353, in write
    bytes_per_second, block_align, bit_depth)
error: ushort format requires 0 <= number <= USHRT_MAX

由于我的值在16位格式下介于-4391和4389之间,所以应该没问题。但我的数据看起来被解释为ushort。


你的问题中的链接已失效... - Jean-François Fabre
1个回答

20
scipy.io.wavfile 中的 write 函数期望输入数组的形状为 (num_samples, num_channels)。我怀疑您的数组形状为 (num_channels, num_samples)。然后,write 尝试将 num_samples 放入一个结构体中的 16 位字段中,该结构体被写入 WAV 文件,但 num_samples 的值对于 16 位值来说太大了。(如果 num_samples 足够小,您将不会收到错误消息,但文件将不具有正确的格式。)

一种快速的解决方法是编写您数组的转置:

wavfile.write(outWaveFileName, 44100, stereoAudio.T)
例如,这里有一些代码演示了错误; xy 的形状为(2,40000):
In [12]: x = (2*np.random.rand(2, 40000) - 1).astype(np.float32)

In [13]: y = (x*32767).astype('int16')

In [14]: from scipy.io import wavfile

In [15]: wavfile.write('foo.wav', 44100, y)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-15-36b8cd0e729c> in <module>()
----> 1 wavfile.write('foo.wav', 44100, y)

/Users/warren/anaconda/lib/python2.7/site-packages/scipy/io/wavfile.pyc in write(filename, rate, data)
    351 
    352         fmt_chunk_data = struct.pack('<HHIIHH', format_tag, channels, fs,
--> 353                                      bytes_per_second, block_align, bit_depth)
    354         if not (dkind == 'i' or dkind == 'u'):
    355             # add cbSize field for non-PCM files

error: ushort format requires 0 <= number <= USHRT_MAX

将数组转置,以便输入到wavfile.write函数的形状符合预期:

In [16]: wavfile.write('foo.wav', 44100, y.T)

阅读回数据以验证其按预期工作:

In [22]: fs, z = wavfile.read('foo.wav')

In [23]: np.allclose(z, y.T)
Out[23]: True

谢谢,你是对的,我的数组是(num_channels,num_samples) - Nico AD

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