这让我头痛了一天,但是因为我想明白了,所以我想将它发布到某个地方以防万一它有帮助。使用wave(不是scipy.io.wavfile)模块将numpy数组写入波形缓冲区中
我正在使用python的wave模块将数据写入wave文件。我不使用scipy.io.wavfile,因为数据可能是一个巨大的矢量(16kHz的音频小时数),我不想/不能一次加载到内存中。我的理解是,scipy.io.wavfile只给你全文界面,而wave可以让你读写缓冲区。如果我错了,我很想纠正这个问题。
我遇到的问题归结为如何将float数据转换为wave.writeframes函数的字节。我的数据没有按正确的顺序写入。这是因为我用的是numpy.getbuffer()函数将数据转换成字节转换,这不尊重数据的方向:
x0 = np.array([[0,1],[2,3],[4,5]],dtype='int8')
x1 = np.array([[0,2,4],[1,3,5]],dtype='int8').transpose()
if np.array_equal(x0, x1):
print "Data are equal"
else:
print "Data are not equal"
b0 = np.getbuffer(x0)
b1 = np.getbuffer(x1)
结果:
Data are equal
In [453]: [b for b in b0]
Out[453]: ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05']
In [454]: [b for b in b1]
Out[454]: ['\x00', '\x02', '\x04', '\x01', '\x03', '\x05']
我假定顺序的字节数由内存中的初始分配决定,因为numpy.transpose()不会重写数据,只是返回一个视图。然而,因为这个事实被numpy数组的接口所掩盖,所以在知道这是个问题之前进行调试是一件很麻烦的事情。
一个解决方案是使用numpy的的toString()函数:
s0 = x0.tostring()
s1 = x1.tostring()
In [455]: s0
Out[455]: '\x00\x01\x02\x03\x04\x05'
In [456]: s1
Out[456]: '\x00\x01\x02\x03\x04\x05'
这可能是显而易见的人谁第一个说的ToString()函数,但不知何故,我的搜索没有挖就如何任何好的文档为使用scipy.io.wavfile以外的波形文件编写格式化整个numpy数组。所以在这里。只是为了完成(注意,“功能”是最初n_channels X N_SAMPLES次,这就是为什么我有这个数据顺序问题开始:
outfile = wave.open(output_file, mode='w')
outfile.setnchannels(features.shape[0])
outfile.setframerate(fs)
outfile.setsampwidth(2)
bytes = (features*(2**15-1)).astype('i2').transpose().tostring()
outfile.writeframes(bytes)
outfile.close()
相反tostring'的',您可以用'struct.pack ',它允许你指定字节顺序和大小。参见http://stackoverflow.com/a/19999599/120261用'struct.unpack'阅读,希望这将是一个有用的起点,如果你想尝试这种其他方式。 – mtrw 2015-02-17 21:11:39
尝试''np.getbuffer(x1.ravel())''。另外,如何使用''x0.tofile()''而不是''x0.tostring()''?如果你关心Endianess,请阅读http://docs.scipy.org/doc/numpy/user/basics.byteswapping.html – Dietrich 2015-02-17 23:04:42
我忘记了:创建多维数组时,可以使用参数''order''来确定它们被写入内存的方式:http://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html – Dietrich 2015-02-17 23:11:02