将 wav 数据的左声道读入 numpy 数组

Read left channel of wav data into numpy array

我正在使用 pyaudio 从麦克风获取输入或读取 wav 文件,并在播放时分析流。如果输入是立体声,我只想分析右声道。我已经能够提取数据并使用循环转换为整数:

        levels = []
        length = len(data)
        if channels == 1:
            for i in range(length//2):
                volume = abs(struct.unpack('<h', data[i:i+2])[0])
                levels.append(volume)
        elif channels == 2:
            for i in range(length//4):
                j = 4 * i + 2
                volume = abs(struct.unpack('<h', data[j:j+2])[0])
                levels.append(volume)

我认为这工作正常,我知道 运行s 在笔记本电脑和 Raspberry Pi 3 上没有错误,但在 运行 Raspberry Pi 同时将输出流式传输到扬声器时为零。我认为消除循环并使用 numpy 可能会有所帮助。我假设我需要使用 np.ndarray 来执行此操作,第一个参数将是 (CHUNK,),其中 CHUNK 是我用于分析音频的块大小(我使用的是 1024)。我认为格式应该是“

您正在从二进制文件中读取 16 位整数。似乎您首先使用 data = f.read() 之类的内容将数据读入 data 变量,此处不可见。然后你做:

for i in range(length//2):
    volume = abs(struct.unpack('<h', data[i:i+2])[0])
    levels.append(volume)

顺便说一句,那个代码是错误的,它应该是 abs(struct.unpack('<h', data[2*i:2*i+2])[0]),否则你会重叠来自不同值的字节。

要对 numpy 做同样的事情,你应该这样做(而不是 f.read() 和整个循环):

data = np.fromfile(f, dtype='<i2')

在我对 5 MB 数据的测试中,这比上面的手动方法快 100 多倍。

在第二种情况下,您有左右交错的值。同样,您可以全部阅读(假设您有足够的内存),然后只访问其中的一半:

data = np.fromfile(f, dtype='<i2')
left = data[::2]
right = data[1::2]

这处理了一切,即使你只需要一半,但它仍然快得多。


编辑: 如果 data 不是来自文件,np.fromfile 可以替换为 np.frombuffer。然后你有这个:

channel_data = np.frombuffer(data, dtype='<i2')
if channels == 2:
    channel_data = channel_data[1::2]
levels = np.abs(channel_data)