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

shi*_*iva 16 python audio sampling pyaudio python-2.7

在浏览了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()
Run Code Online (Sandbox Code Playgroud)

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

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()
Run Code Online (Sandbox Code Playgroud)
  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])返回4133,但len(frames[0])返回4096.
  7. for循环执行int(RATE / CHUNK * RECORD_SECONDS)时间,我不明白为什么.是"Ruben Sanchez"回答的同一个问题,但我不能确定他说的是否正确CHUNK=bytes.而根据他的解释,那一定是int(RATE / (CHUNK*2) * RECORD_SECONDS)因为(CHUNK*2)在缓冲区,每次重复读取的样本数量.
  8. 最后,当我写print frames[0],它打印乱码,因为它试图将字符串视为ASCII编码,它不是,它只是一个字节流.那么如何使用struct模块以十六进制打印这个字节流?如果以后,我用我选择的值更改每个十六进制值,它是否仍会产生可播放的声音?

无论我上面写的是我对事物的理解,其中许多可能是错的.

Mat*_*ias 22

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

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

  • @Koffiman 使用 PyAudio,样本是交错的。底层 PortAudio 库支持一个标志 [paNonInterleaved](http://www.portaudio.com/docs/v19-doxydocs/portaudio_8h.html#a1d79f0b88812cef5364b276dbbc898b5) 来改变它,但这在 Python 包装器中通常不可用。请注意,`paNonInterleaved` 为每个通道使用单独的指针,即整个音频数据不一定包含在单个连续的内存块中。 (2认同)