为什么 PyAudio 会切断 NumPy 数组的音频?

Why does PyAudio cut off audio from NumPy array?

我在使用 PyAudio 时不小心忘记了将一些 NumPy 数组转换为字节 objects,但令我惊讶的是它仍然 播放了音频,即使听起来有点不对劲.我写了一个小测试脚本(见下文)来播放 1 秒的 440Hz 音调,似乎将 NumPy 数组直接写入 PyAudio Stream 会缩短音调。

谁能解释为什么会这样?我认为 NumPy 数组是一个连续的字节序列,其中包含一些关于其 dtype 和步幅的 header 信息,所以我会预测 PyAudio 在 header, 不切音.

# script segment
import pyaudio
import numpy as np
RATE = 48000

p = pyaudio.PyAudio()
stream = p.open(format = pyaudio.paFloat32, channels = 1, rate = RATE, output = True)

TONE = 440
SECONDS = 1
t = np.arange(0, 2*np.pi*TONE*SECONDS, 2*np.pi*TONE/RATE) 
sina = np.sin(t).astype(np.float32)
sinb = sina.tobytes()

# console commands segment
stream.write(sinb) # bytes object plays 1 second of 440Hz tone
stream.write(sina) # still plays 440Hz tone, but noticeably shorter than 1 second

问题比您描述的更微妙。您的第一个调用传递了一个大小为 192,000 的字节数组。第二个调用传递了一个大小为 48,000 的 float32 值列表。 pyaudio 处理它们,并将缓冲区传递给 portaudio 进行播放。

但是,当您打开 pyaudio 时,您告诉它您正在发送 paFloat32 数据,每个样本有 4 个字节。 pyaudio write 处理程序获取您给它的数组的长度,然后除以通道数乘以样本大小以确定有多少音频样本。在您的第二次调用中,数组的长度为 48,000,除以 4,从而告诉 portaudio“这里有 12,000 个样本”。

因此,每个人都了解格式,但对大小感到困惑。如果将第二次调用更改为

stream.write(sina, 48000)

那就没人猜了,而且效果很好。