0

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

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 是否可以实现低附加延迟,如果可以,哪些模块更适合此目的。

4

1 回答 1

6

pygame 是延迟的原因吗?

可能不是。

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

SDL_mixerSDL——或者更确切地说——很容易成为问题所在。

因此,您可能需要了解一些有关 SDL 的知识,才能pygame用于超出通常游戏风格需求的音频。带有 SDL 的音频是一个很好的概述,尽管它似乎有点过时了。


首先要考虑的是您使用的音频驱动程序。例如,在许多 linux 系统上,ALSA 不能做低延迟的声音,这意味着你写的任何最终与 ALSA 对话的东西也不能做。如果您的系统设置为使用esd或其他声音守护程序(如果可能)并在必要时回退,您显然不希望在此处使用。所以,如果这样的事情是你的问题,你将不得不配置SDL_mixer使用不同的驱动程序。


pygame.mixer假设驱动程序可以处理它,那么绝对可以使用/发出低延迟的声音SDL_mixer。但它可能无法开箱即用。

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

另请注意,SDL_mixer如果它们不在相同的采样率/等下,它将自动在您的背后重新编码您的声音。作为目标,这不仅为 CPU 工作增加了一点延迟,还意味着实际缓冲区大小与您认为正在使用的缓冲区无关......</p>

另一种方法是绕过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.

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

于 2013-12-10T21:59:58.663 回答