【问题标题】:Real-time audio signal processing using python使用python进行实时音频信号处理
【发布时间】:2018-03-05 06:57:44
【问题描述】:

我一直在尝试使用 python 中的“pyAudio”模块进行实时音频信号处理。我所做的是从麦克风读取音频数据并通过耳机播放的简单案例。我尝试使用以下代码(Python 和 Cython 版本)。认为它有效,但不幸的是它是摊位并且不够平滑。我怎样才能改进代码,使它能够顺利运行。我的电脑是 i7,8GB RAM。

Python 版本

import pyaudio
import numpy as np

RATE    = 16000
CHUNK   = 256

p               =   pyaudio.PyAudio()

player = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, output=True, 
frames_per_buffer=CHUNK)
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK)

for i in range(int(20*RATE/CHUNK)): #do this for 10 seconds
player.write(np.fromstring(stream.read(CHUNK),dtype=np.int16))
stream.stop_stream()
stream.close()
p.terminate()

赛通版本

import pyaudio
import numpy as np

cdef int RATE   = 16000
cdef int CHUNK  = 1024
cdef int i      
p               =   pyaudio.PyAudio()

player = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, output=True, frames_per_buffer=CHUNK)
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK)

for i in range(500): #do this for 10 seconds
    player.write(np.fromstring(stream.read(CHUNK),dtype=np.int16))
stream.stop_stream()
stream.close()
p.terminate()

【问题讨论】:

  • 不知道您所说的“摊位”是什么意思以及您的期望。使用 cython 没有任何收获 - 没有 python 计算,一切都由库内的 c 代码完成。你称它为实时,但使用阻塞 IO - 它应该如何工作?使用非阻塞版本people.csail.mit.edu/hubert/pyaudio/docs/…
  • “摊位”是指中间的音频中断。阻塞模式和非阻塞模式有什么区别?,谢谢你的链接。
  • 在您的情况下,“阻塞”是指播放时不录制,录制时不播放
  • @ead ,虽然非阻塞可用于将输入(麦克风)直接连接到输出(耳机/扬声器),但您无法对音频进行任何处理,因为您无法访问/控制它.对于任何中流处理,OP 都需要使用阻塞版本(他正在使用)。
  • @SAJIL C K,请检查我的答案以获得解决方案。

标签: python audio signals real-time cython


【解决方案1】:

我相信您缺少 CHUNK 作为 player.write 调用的第二个参数。

player.write(np.fromstring(stream.read(CHUNK),dtype=np.int16),CHUNK)

另外,不确定它是否是格式错误。但是player.write 需要被标记到for 循环中

根据pyaudio site,您需要有RATE / CHUNK * RECORD_SECONDS 而不是RECORD *RATE/CHUNK,因为python/ 除法之前执行* 乘法。

for i in range(int(20*RATE/CHUNK)): #do this for 10 seconds
    player.write(np.fromstring(stream.read(CHUNK),dtype=np.int16),CHUNK)

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

最后,您可能希望将 rate 增加到 44100CHUNK1024CHANNEL2 以获得更好的保真度。

【讨论】:

  • 感谢您的帮助。我试过你的建议。将“CHUNK”作为“玩家”对象的参数后,情况好多了,但仍然出现错误“ALSA lib pcm.c:7843:(snd_pcm_recover) underrun occurred”。我做了一些研究,发现它与缓冲区大小有关。所以我尝试了“CHUNK”大小,发现 128 是一个不错的值。它仍然会出现相同的错误,但仅在最初的几秒钟内它工作得非常好。
  • 我试图对你的答案进行投票,但我没有足够的声誉来这样做。
  • 如果对您的问题有帮助,通常会在 SO 上选择答案。它有助于关闭循环,还可以为您的帐户添加积分。请参阅此处了解如何接受答案:meta.stackexchange.com/questions/5234/…
  • 不需要。如果你看到这样的统计数据,即使提供了有效的答案,许多问题也没有得到解决。这会产生“噪音”并扭曲统计数据。我也在指导新人。希望对您有所帮助。
  • 很多在线示例,包括其他问题,似乎缺少来自write() 的参数CHUNK - 添加这个解决了我的问题。我听到奇怪/嗡嗡的声音。与问题 OP 不同的问题
【解决方案2】:

下面的代码将采用默认输入设备,并将记录的内容输出到默认输出设备中。

import PyAudio
import numpy as np

p = pyaudio.PyAudio()

CHANNELS = 2
RATE = 44100

def callback(in_data, frame_count, time_info, flag):
    # using Numpy to convert to array for processing
    # audio_data = np.fromstring(in_data, dtype=np.float32)
    return in_data, pyaudio.paContinue

stream = p.open(format=pyaudio.paFloat32,
                channels=CHANNELS,
                rate=RATE,
                output=True,
                input=True,
                stream_callback=callback)

stream.start_stream()

while stream.is_active():
    time.sleep(20)
    stream.stop_stream()
    print("Stream is stopped")

stream.close()

p.terminate()

这将运行 20 秒然后停止。方法回调是您可以处理信号的地方: audio_data = np.fromstring(in_data, dtype=np.float32)

return in_data 是您将后处理数据发送回输出设备的位置。

Note 块的默认参数为 1024,如 PyAudio 文档中所述: http://people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.PyAudio.open

【讨论】:

    【解决方案3】:

    我正在做一个类似的项目。我修改了你的代码,现在摊位已经消失了。块越大延迟越大。这就是我保持低的原因。

    import pyaudio
    import numpy as np
    
    CHUNK = 2**5
    RATE = 44100
    LEN = 10
    
    p = pyaudio.PyAudio()
    
    stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK)
    player = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, output=True, frames_per_buffer=CHUNK)
    
    
    for i in range(int(LEN*RATE/CHUNK)): #go for a LEN seconds
        data = np.fromstring(stream.read(CHUNK),dtype=np.int16)
        player.write(data,CHUNK)
    
    
    stream.stop_stream()
    stream.close()
    p.terminate()
    

    【讨论】:

      猜你喜欢
      • 2013-06-07
      • 2021-01-21
      • 2012-11-01
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 2018-01-17
      • 2012-11-05
      • 2014-03-26
      相关资源
      最近更新 更多