【问题标题】:How to plot pyaudio input with matplotlib?如何使用 matplotlib 绘制 pyaudio 输入?
【发布时间】:2015-12-16 09:14:19
【问题描述】:

如何在来自麦克风的 matplotlib 输入信号上绘图? 我试图用 plt.plot(frames) 绘图,但由于某种原因,frames 是一个字符串?

a) 为什么 frames 变量是一个字符串列表?

b) 为什么数据变量是字符串列表?

c) 它们应该代表单个样本的能量/幅度并且是整数吗?

d) 当我指定我想要 1024 的块大小时,为什么数据长度是 2048?

(我猜是因为我使用了 paInt16,但仍然看不到为什么它不能是 1024)

我有以下麦克风输入代码:

import pyaudio
import audioop
import matplotlib.pyplot as plt
import numpy as np
from itertools import izip
import wave


FORMAT = pyaudio.paInt16                # We use 16bit format per sample
CHANNELS = 1
RATE = 44100
CHUNK = 1024                            # 1024bytes of data red from a buffer
RECORD_SECONDS = 3
WAVE_OUTPUT_FILENAME = "file.wav"

audio = pyaudio.PyAudio()

# start Recording
stream = audio.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE, input=True,
                    frames_per_buffer=CHUNK)

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

stream.stop_stream()
stream.close()
audio.terminate()

【问题讨论】:

  • 您可以在示例代码中包含您的导入语句吗?此外,frames 变量是一个字符串列表,因为您将其声明为 frames = ''.join(frames)。你不需要这样做,因为你已经附加了所有你需要的帧,你有一个列表。
  • 是的,我知道这一点,但数据也是一个字符串。我认为 struct.unpack 需要做一些事情,但我不知道具体是什么。
  • 但是你问为什么frames 是一个字符串列表?无论如何,Stream.read() 应该返回一个字符串,如 API 文档中所指定:people.csail.mit.edu/hubert/pyaudio/docs
  • 在python3中需要在前面加上bb"".join(frames)

标签: python matplotlib speech-recognition


【解决方案1】:

a) 为什么 frames 变量是一个字符串列表?

由于 b),这就是您在代码中构建它的方式。

b) 为什么数据变量是字符串列表?

它是一个字节串,它只是一个原始的字节序列。这就是read() 返回的内容。

c) 它们应该代表单个样本的能量/幅度并且是整数吗?

他们是。它们只是打包在一个字节序列中,而不是 Python 整数。

d) 当我指定我想要 1024 的块大小时,为什么数据长度是 2048?

1024帧数。每帧有 2 个字节长,所以你得到 2048 个字节。

如何在来自麦克风的 matplotlib 输入信号上绘图?我试图用 plt.plot(frames) 绘图,但由于某种原因,frames 是一个字符串?

取决于您要绘制的内容。通过将字节字符串转换为numpy数组可以获得原始幅度:

fig = plt.figure()
s = fig.add_subplot(111)
amplitude = numpy.fromstring(frames, numpy.int16)
s.plot(amplitude)
fig.savefig('t.png')

更有用的情节是spectrogram

fig = plt.figure()
s = fig.add_subplot(111)
amplitude = numpy.fromstring(frames, numpy.int16)
s.specgram(amplitude)
fig.savefig('t.png')

但是您可以随意修改幅度,因为您有一个 numpy 数组。

【讨论】:

  • 为什么必须用dtype=int16声明numpy数组?
  • numpy 无法从原始字节字符串中推断出存储了什么样的变量,您必须明确指定它。由于数据被读取为pyaudio.paInt16,因此字符串包含 2 字节有符号整数,这就是我告诉numpy 读取的内容。
  • 我明白了。我不是 OP,我对音频一无所知,但是 16 位是标准样本大小,这意味着测量的强度值具有 16 位的精度吗?而且,“样本”是否只是声音的一个“单位”,其持续时间会产生一个离散的强度值?
  • 一种标准,我猜,至少对于非专业人士来说。我自己从未使用过pyaudio,但我怀疑如果原始文件中的分辨率不是 16 位,它会将分辨率转换为 16 位。是的,一帧是一次测量(每秒进行 44100 次)。它可能包含多个通道(立体声等),但在这种情况下只有一个。
猜你喜欢
  • 2018-03-05
  • 1970-01-01
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多