使用Python的音频低延迟

时间:2013-12-10 19:55:30

标签: python audio latency asio low-latency

使用pygame音频播放时,我注意到高延迟(> 100 ms):

import pygame

pygame.init()
pygame.mixer.init()
sounda = pygame.mixer.Sound("test.wav")

def callback()
    sounda.play()

# callback is called by another function, but I could measure a high latency (> 100ms)

pygame导致延迟吗?更一般地说,使用Python可以低延迟音频播放吗?

应用程序示例:当MIDI信息从MIDI键盘到达时播放一些.wav文件。 (我想编写一个非常非常基本的音乐采样器)。 当然,延迟将在很大程度上取决于音频接口(ASIO或ASIO等),但我现在想分析Python是否可以实现低附加延迟,如果是这样,那么哪个模块是首选。< / p>

1 个答案:

答案 0 :(得分:6)

  

pygame是延迟的原因吗?

可能不是。

Pygame只是SDL的包装。在某些领域 - 比如这个 - 它是一个非常薄的包装。

但SDL - 或者更确切地说,SDL_mixer - 可能很容易成为问题。

因此,您可能需要了解SDL,以便将pygame用于超出通常游戏风格需求的音频。 Audio with SDL是一个很好的概述,虽然看起来有点过时了。


首先要考虑的是你正在使用的音频驱动程序。例如,在许多Linux系统上,ALSA无法进行低延迟声音,这意味着您编写的最终与ALSA对话的任何内容都无法做到。如果您的系统设置为尽可能使用esd或其他声音守护程序并在必要时退回,那么您显然不希望这样。因此,如果您遇到类似问题,则必须配置SDL_mixer以使用其他驱动程序。


假设驱动程序可以处理它,肯定可以使用pygame.mixer / SDL_mixer执行低延迟声音。但它可能无法开箱即用。

您要做的第一件事是选择比默认值更小的缓冲区大小。

另请注意,SDL_mixer会自动重新编码您背后的声音,如果它们的采样率不同/等。作为目标,它不仅为CPU工作增加了一点延迟,还意味着真正的缓冲区大小与你认为正在使用的那个没有任何关系......

另一种方法是绕过pygame.mixer / SDL_mixer,自行混音,然后直接转到pygame.sound / SDL_sound。这仍然会有相同的驱动程序问题,但SDL_mixer引起的任何事情(如重新编码)都会消失。

如果你不能让pygame / SDL做你想做的事情(例如,因为它在你的系统上支持的唯一驱动程序都很糟糕),你将不得不使用不同的库。 wiki上的PythonInMusic有数百个链接,您还可以搜索PyPI。但是,您可能希望从另一端开始 - 找到要使用的C音频库,然后为其搜索Python绑定。例如,pyAudio是PortAudio的一个相对较薄的包装器,所以如果PortAudio的可移植性,可配置性和性能要求满足您的需求并且其API适合您的设计,那么它就会撼动,但它却很糟糕。


另一个可能出错的地方是你的代码。

在你的情况下,这显然不是问题,因为你所做的只是给pygame.mixer预先制作的声音。但是,如果您决定将声音和提要缓冲区预先转换为pygame.sound,则可能会遇到Python循环缓慢且算术速度慢的问题。

“慢”是指微秒级。每20ms缓冲一次循环不是问题。每个样本循环一次可能是。如果您正在进行任何处理,您应该考虑使用NumPy或专用音频库来执行繁琐的工作而不是纯Python。