使用pyaudio时什么是块、样本和帧

What are chunks, samples and frames when using pyaudio

看了pyaudio的文档,看了网上的其他文章,不知自己的理解是否正确。

这是在pyaudio网站上找到的录音代码:

import pyaudio
import wave

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

print("* recording")

frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    frames.append(data)

print("* done recording")

stream.stop_stream()
stream.close()
p.terminate()

如果我添加这些行,那么我就可以播放我录制的任何内容:

play=pyaudio.PyAudio()
stream_play=play.open(format=FORMAT,
                      channels=CHANNELS,
                      rate=RATE,
                      output=True)
for data in frames: 
    stream_play.write(data)
stream_play.stop_stream()
stream_play.close()
play.terminate()
  1. "RATE"是每秒收集的样本数。
  2. "CHUNK"是缓冲区中的帧数。
  3. 每帧将有 2 个样本作为 "CHANNELS=2"。
  4. 每个样本的大小为 2 个字节,使用函数计算:pyaudio.get_sample_size(pyaudio.paInt16).
  5. 因此每个帧的大小为 4 个字节。
  6. 在"frames"列表中,每个元素的大小必须为1024*4字节,例如frames[0]的大小必须为4096字节。然而, sys.getsizeof(frames[0])returns4133,但是len(frames[0])returns4096.
  7. for 循环执行 int(RATE / CHUNK * RECORD_SECONDS) 次,我不明白为什么。 Here 是 "Ruben Sanchez" 回答的同一个问题,但我不能确定他说的是否正确 CHUNK=bytes。根据他的解释,它必须是 int(RATE / (CHUNK*2) * RECORD_SECONDS),因为 (CHUNK*2) 是每次迭代在缓冲区中读取的样本数。
  8. 最后,当我写 print frames[0] 时,它打印出乱码,因为它试图将字符串视为 ASCII 编码,但实际上它不是,它只是一个字节流。那么如何使用 struct 模块以十六进制打印这个字节流呢?如果稍后,我用我选择的值更改每个十六进制值,它仍然会产生可播放的声音吗?

上面写的都是我对事情的理解,可能有很多是错误的。

  1. "RATE"是"sampling rate",即每秒帧数
  2. "CHUNK" 是 帧的(任意选择的)数量 在这个例子中(可能很长)信号被分割成
  3. 是的,每个帧将有 2 个样本作为 "CHANNELS=2",但术语 "samples" 很少用于此上下文(因为它令人困惑)
  4. 是的,本例中每个样本的大小为 2 个字节(= 16 位)
  5. 是的,每帧大小为4字节
  6. 是的,"frames"的每个元素应该是4096字节。 sys.getsizeof() 报告 Python 解释器所需的存储 space,这通常比原始数据的实际大小多一点。
  7. RATE * RECORD_SECONDS 是应该记录的 的数量。由于 for 循环不会对每个 frame 重复,而只会对每个 chunk 重复,因此循环次数必须除以块大小 CHUNK。这与samples无关,所以不涉及2的因素。
  8. 如果你真的想看到十六进制值,你可以试试[hex(x) for x in frames[0]]。如果您想获得实际的 2 字节数字,请使用带有 struct 模块的格式字符串 '<H'

您可能对我关于使用 wave 模块读取 WAV 文件的教程感兴趣,其中更详细地涵盖了您的一些问题:http://nbviewer.jupyter.org/github/mgeier/python-audio/blob/master/audio-files/audio-files-with-wave.ipynb