使用麦克风输入的Python Librosa

11

我正在尝试让librosa能够使用麦克风输入而不仅仅是wav文件,但遇到了一些问题。起初我使用pyaudio库连接到麦克风,但我在将这些数据转换为librosa可用的形式时遇到了问题。有什么建议吗?或者这是否可能实现?

我尝试了几件事情,包括接收来自pyaudio麦克风的数据,将其解码为浮点数组并将其传递给librosa(根据文档,这就是librosa处理.wav文件的方式),但它不起作用,因为它会产生以下错误:

"librosa.util.exceptions.ParameterError: Audio buffer is not finite everywhere"


FORMAT = pyaudio.paInt16
RATE = 44100
CHUNK = 2048
WIDTH = 2
CHANNELS = 2
RECORD_SECONDS = 5

stream = audio.open(format=FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    input=True,
                    output=True,
                    frames_per_buffer=CHUNK)
while True:
        data = stream.read(CHUNK)
        data_float = np.fromstring(data , dtype=np.float16)
        data_np = np.array(data_float , dtype='d')
        # data in 1D array
        mfcc = librosa.feature.mfcc(data_np.flatten() , 44100)
        print(mfcc)


我认为事情并不像你说的那么简单。你正在尝试进行实时的音频录制和处理! - Ahmad Moussa
1
嘿@AhmadMoussa,是的,这绝对不像我最初想象的那么简单。就像我在YouTube上跟随[https://www.youtube.com/watch?v=AShHJdSIxkY]一样,使用pyaudio从麦克风输入生成实时正弦波,并且我想知道是否可以使用librosa做类似的事情来实时收集MFCC等信息,但我不知道这是否可行,或者是否有其他方法。再次感谢! - Vince
1个回答

12
你可以使用来自pyaudio回调函数来完成。我认为使用类更容易。
在构造函数__init__中,您定义所有需要的常量,并将FORMAT设置为pyaudio.paFloat32,这将使您稍后能够与librosa一起使用。
然后,在start方法中,我打开音频流。在.open()中,stream_callback参数允许您指定要实现函数的方式。 回调函数方法以in_data, frame_count, time_info, flag作为参数,然后您会收到二进制形式的in_data。因此,您需要使用np.frombuffer(in_data, dtype=np.float32)将它们转换为numpy数组。
完成后,您可以像平常使用librosa一样使用您的numpy.ndarray 我认为这可以进行优化,但是这个解决方案对我很有效,希望它可以帮助您 :)
import numpy as np
import pyaudio
import time
import librosa

class AudioHandler(object):
    def __init__(self):
        self.FORMAT = pyaudio.paFloat32
        self.CHANNELS = 1
        self.RATE = 44100
        self.CHUNK = 1024 * 2
        self.p = None
        self.stream = None

    def start(self):
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=self.FORMAT,
                                  channels=self.CHANNELS,
                                  rate=self.RATE,
                                  input=True,
                                  output=False,
                                  stream_callback=self.callback,
                                  frames_per_buffer=self.CHUNK)

    def stop(self):
        self.stream.close()
        self.p.terminate()

    def callback(self, in_data, frame_count, time_info, flag):
        numpy_array = np.frombuffer(in_data, dtype=np.float32)
        librosa.feature.mfcc(numpy_array)
        return None, pyaudio.paContinue

    def mainloop(self):
        while (self.stream.is_active()): # if using button you can set self.stream to 0 (self.stream = 0), otherwise you can use a stop condition
            time.sleep(2.0)


audio = AudioHandler()
audio.start()     # open the the stream
audio.mainloop()  # main operations with librosa
audio.stop()

谢谢您的回答!我会尝试这个方法,我之前的解决方案是录制一定时间的音频(一旦音频通过了设定的振幅),保存为wav文件,然后使用librosa,虽然我的解决方案不太理想。 :) - Vince

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