And*_*rtz 6 python audio numpy wave
这让我感到头疼一天,但是因为我已经弄清楚了,所以我想把它贴在某个地方以防它有用.
我正在使用python的wave模块将数据写入wave文件.我不使用scipy.io.wav文件,因为数据可以是一个巨大的向量(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)
Run Code Online (Sandbox Code Playgroud)
结果:
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']
Run Code Online (Sandbox Code Playgroud)
我假设字节的顺序由内存中的初始分配决定,因为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'
Run Code Online (Sandbox Code Playgroud)
对于首先说tostring()函数的人来说,这可能是显而易见的,但不知怎的,我的搜索并没有挖掘出任何关于如何格式化整个numpy数组以进行波形文件编写而不是使用scipy.io.wavfile的文档.所以这就是.只是为了完成(请注意,"功能"最初是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()
Run Code Online (Sandbox Code Playgroud)
对我来说tostring
效果很好。请注意,在 WAVE 中,8 位文件必须签名,而其他文件(16 位或 32 位)必须未签名。
一些对我有用的肮脏的演示代码:
import wave
import numpy as np
SAMPLERATE=44100
BITWIDTH=8
CHANNELS=2
def gensine(freq, dur):
t = np.linspace(0, dur, round(dur*SAMPLERATE))
x = np.sin(2.0*np.pi*freq*t)
if BITWIDTH==8:
x = x+abs(min(x))
x = np.array( np.round( (x/max(x)) * 255) , dtype=np.dtype('<u1'))
else:
x = np.array(np.round(x * ((2**(BITWIDTH-1))-1)), dtype=np.dtype('<i%d' % (BITWIDTH/8)))
return np.repeat(x,CHANNELS).reshape((len(x),CHANNELS))
output_file="test.wav"
outfile = wave.open(output_file, mode='wb')
outfile.setparams((CHANNELS, BITWIDTH/8, SAMPLERATE, 0, 'NONE', 'not compressed'))
outfile.writeframes(gensine(440, 1).tostring())
outfile.writeframes(gensine(880, 1).tostring())
outfile.close()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2633 次 |
最近记录: |