1

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

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 的语言特性。任何方向将不胜感激。

4

2 回答 2

2

您的问题来自于 wave 库只是为您提供原始二进制数据(以字符串的形式)的事实。

您可能需要使用 . 检查数据的形式self.wf.getparams()。这返回(nchannels, sampwidth, framerate, nframes, comptype, compname)。如果您确实有 1 个通道,样本宽度为 2,并且没有压缩(相当常见的波形类型),您可以使用以下命令(将 numpy 作为 np 导入)来获取数据:

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

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

有关执行此操作的其他方法,请参阅在 Python 中读取 *.wav 文件。

Numpyless 版本

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

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

这像以前一样工作(用 测试plot(byteList); show())。'h' 表示有符号短。len等作品。这确实会一次全部导入 wav 文件,但是 .wav 通常很小。不总是。

于 2013-05-20T19:09:18.003 回答
1

我通常为此使用数组模块fromstring方法。

我对数据块进行操作的标准模式是这样的:

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

圭多不会错...

如果您更喜欢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)
于 2013-05-20T18:54:08.640 回答