gpt4 book ai didi

python - 使用 wave(不是 scipy.io.wavfile)模块将 numpy 数组写入缓冲区中的 wave 文件

转载 作者:太空狗 更新时间:2023-10-30 00:17:15 25 4
gpt4 key购买 nike

这让我头疼了一天,但既然我已经弄明白了,我想把它贴在某个地方以防它有帮助。

我正在使用 python 的 wave 模块将数据写入 wave 文件。我没有使用 scipy.io.wavfile,因为数据可能是一个巨大的向量(16kHz 的音频小时数),我不想/不能一次全部加载到内存中。我的理解是 scipy.io.wavfile 只给你完整的文件接口(interface),而 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() 不会重写数据而只是返回一个 View 。然而,由于这个事实被 numpy 数组的接口(interface)所掩盖,在知道这是问题所在之前进行调试是一件很麻烦的事情。

一个解决方案是使用 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 数组以编写 wave 文件的好文档.所以就在这里。只是为了完成(请注意,“功能”最初是 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 工作正常。请注意,在 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()

关于python - 使用 wave(不是 scipy.io.wavfile)模块将 numpy 数组写入缓冲区中的 wave 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28570370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com