Python Wave Library字符串到字节

时间:2013-05-20 18:26:39

标签: python python-2.7 wav

所以基本上我试图读取波形文件的信息,以便我可以获取字节信息并创建一个时间 - >幅度点数组。

import wave

class WaveFile:

    # `filename` is the name of the wav file to open
    def __init__(self, fileName):
        self.wf = wave.open(fileName, 'r')
        self.soundBytes = self.wf.readframes(-1)
        self.timeAmplitudeArray = self.__calcTimeAmplitudeArray()


     def __calcTimeAmplitudeArray(self):
         self.internalTimeAmpList = [] # zero out the internal representation

         byteList = self.soundBytes
         if((byteList[i+1] & 0x080) == 0):
             amp = (byteList[i] & 0x0FF) + byteList[i+1] << 8
             #more code continues.....

错误:

if((int(byteList[i+1]) & 0x080) == 0):
TypeError: unsupported operand type(s) for &: 'str' and 'int'

我尝试使用int()转换为整数类型,但无济于事。我来自Java背景,这可以使用byte类型完成,但这似乎不是Python的语言特性。任何方向都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

你的问题来自于wave库只是给你原始的二进制数据(以字符串的形式)。

您可能需要使用self.wf.getparams()检查数据的格式。这将返回(nchannels, sampwidth, framerate, nframes, comptype, compname)。如果你有1个通道,样本宽度为2,没有压缩(相当常见的wave类型),你可以使用以下(import numpy as np)来获取数据:

byteList = np.fromstring(self.soundBytes,'<h')

这将返回带有数据的numpy数组。你不需要循环。如果你有不同的样本宽度,你需要在第二个参数中有不同的东西。我已经使用简单的.wav文件和plot(byteList); show()(iPython中的pylab模式)进行了测试。

有关其他方法,请参阅Reading *.wav files in Python

Numpyless版本

如果你需要避免numpy,你可以这样做:

import array
bytelist = array.array('h')
byteList.fromstring(self.soundBytes)

这与以前一样(使用plot(byteList); show()测试)。 'h'表示签名短。 len等有效。这确实一次导入了wav文件,但是再次.wav通常很小。并非总是如此。

答案 1 :(得分:1)

我通常使用array-modulefromstring方法。

我操作数据块的标准模式是:

def bytesfromfile(f):
    while True:
        raw = array.array('B')
        raw.fromstring(f.read(8192))
        if not raw:
            break
        yield raw

with open(f_in, 'rb') as fd_in:
    for byte in bytesfromfile(fd_in):
        # do stuff

高于'B'表示无符号字符,即1字节。

如果文件不是很大,那么你可以嘟嘟它:

In [8]: f = open('foreman_cif_frame_0.yuv', 'rb')

In [9]: raw = array.array('B')

In [10]: raw.fromstring(f.read())

In [11]: raw[0:10]
Out[11]: array('B', [10, 40, 201, 255, 247, 254, 254, 254, 254, 254])

In [12]: len(raw)
Out[12]: 152064

Guido can't be wrong ...

如果您更喜欢numpy,我倾向于使用:

    fd_i = open(file.bin, 'rb')
    fd_o = open(out.bin, 'wb')

    while True:
        # Read as uint8
        chunk = np.fromfile(fd_i, dtype=np.uint8, count=8192)
        # use int for calculations since uint wraps
        chunk = chunk.astype(np.int)
        if not chunk.any():
            break
        # do some calculations
        data = ...

        # convert back to uint8 prior to writing.
        data = data.astype(np.uint8)
        data.tofile(fd_o)

    fd_i.close()
    fd_o.close()

或阅读整个文件:

In [18]: import numpy as np

In [19]: f = open('foreman_cif_frame_0.yuv', 'rb')

In [20]: data = np.fromfile(f, dtype=np.uint8)

In [21]: data[0:10]
Out[21]: array([ 10,  40, 201, 255, 247, 254, 254, 254, 254, 254], dtype=uint8)