将实时音频数据读入numpy数组

23

如何将实时音频读入numpy数组并使用matplotlib进行绘制?

目前我是在文件上录制音频,然后使用scikits.audiolab.wavread将其读入数组。 是否有一种直接实时处理的方法吗?

4个回答

32
你可以使用 PyAudio 来录制音频,并使用 np.frombuffer 将其转换为 NumPy 数组。
import pyaudio
import numpy as np
from matplotlib import pyplot as plt

CHUNKSIZE = 1024 # fixed chunk size

# initialize portaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=CHUNKSIZE)

# do this as long as you want fresh samples
data = stream.read(CHUNKSIZE)
numpydata = np.frombuffer(data, dtype=np.int16)

# plot data
plt.plot(numpydata)
plt.show()

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

如果你想录制立体声而不是单声道,你需要将channels设置为2。然后你会得到一个交替的通道数组。你可以像这样改变它的形状:

frame = np.frombuffer(data, dtype=numpy.int16)       # interleaved channels
frame = np.stack((frame[::2], frame[1::2]), axis=0)  # channels on separate axes

谢谢。在我的解决方案中,我使用了alsaaudio而不是pyaudio。这两者之间有什么区别吗? - Ada Xu
2
我认为alsaaudio只适用于Linux,而PyAudio提供了PortAudio绑定并可在多个平台上运行。 - Frank Zalkow
你好@FrankZalkow,能否请您看一下我的问题 - https://stackoverflow.com/questions/53292811/convert-alsaaudio-to-pyaudio 谢谢 - Arun
你能展示一下如何将两个通道解析成一个形状的numpy数组吗? - Petrus Theron

22

有一个名为PyAudio的库,您可以使用它进行实时录音。再加上numpy.fromstring()numpy.hstack()的帮助,您可以获得所需的输出。请注意,以下代码片段是用于MONO-CHANNEL的。

import pyaudio
import numpy

RATE=16000
RECORD_SECONDS = 2.5
CHUNKSIZE = 1024

# initialize portaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNKSIZE)

frames = [] # A python-list of chunks(numpy.ndarray)
for _ in range(0, int(RATE / CHUNKSIZE * RECORD_SECONDS)):
    data = stream.read(CHUNKSIZE)
    frames.append(numpy.fromstring(data, dtype=numpy.int16))

#Convert the list of numpy-arrays into a 1D array (column-wise)
numpydata = numpy.hstack(frames)

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

这是经过测试的代码。它应该能够完美运行。为了检查你记录的数据是否正确地在numpydata中可用,你可以在之前的代码后面添加以下片段。

import scipy.io.wavfile as wav
wav.write('out.wav',RATE,numpydata)

这些代码会将你的numpydata写入到"out.wav"文件中。播放该文件以检查数据。

PS:这是我在StackOverflow的第一次回答。希望能帮到你。


7
第一篇文章写得不错 :) - deW1
2
@deW1 感谢您修改我的答案并突出术语。 :) - stitchesguy90
@StitchesGuy90,我希望能够绘制传入的音频数据,以便实时获得音频图形,这是否可能? - Step

0

这个答案与此处的第一个答案类似,但我包含了绘制音频数据的缺失部分.

import pyaudio
import wave
import numpy as np
import noisereduce as nr

#This library helps us in plotting the  audio
import matplotlib.pyplot as plt 

def plotAudio2(output):
        fig, ax = plt.subplots(nrows=1,ncols=1, figsize=(20,4))
        plt.plot(output, color='blue')
        ax.set_xlim((0, len(output)))
        plt.show()

CHUNK = 22050
FORMAT = pyaudio.paFloat32
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 20

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)
    data_sample = np.frombuffer(data, dtype=np.float32)

    print("data sample")
    plotAudio2(data_sample)

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

我已经测试了上面的代码片段,它对我来说完美地工作。

注意:这个代码片段是在Windows中测试的,而且在MacOS中可能会有一些matplotlib的问题(虽然我不确定)。


-1
import librosa
file = 'audio/a1.wav'
signal, _ = librosa.load(file)
print(type(signal))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接