使用Python实现音频低延迟

使用Python实现音频低延迟,python,audio,latency,asio,low-latency,Python,Audio,Latency,Asio,Low Latency,当使用pygame音频播放时,我注意到延迟很高(>100ms): pygame是延迟的原因吗?更一般地说,Python是否可以进行低延迟音频播放 应用程序示例:当MIDI消息从MIDI键盘到达时,播放一些.wav文件。(我想编写一个非常基本的音乐采样器)。 当然,延迟在很大程度上取决于音频接口(ASIO或非ASIO,等等),但我现在想分析Python是否可以实现低附加延迟,如果可以,则首选哪些模块 pygame是延迟的原因吗 可能不会 Pygame只是SDL的包装。在像这样的一些地区,这是一个非

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

pygame
是延迟的原因吗?更一般地说,Python是否可以进行低延迟音频播放

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

pygame是延迟的原因吗

可能不会

Pygame只是SDL的包装。在像这样的一些地区,这是一个非常薄的包装

但SDL,或者更确切地说,SDL\U混音器可能很容易成为问题

因此,您可能需要了解一下SDL,以便使用
pygame
获得超出常规游戏风格需求的音频。这是一个很好的概述,尽管它似乎有点过时


首先要考虑的是你使用的音频驱动程序。例如,在许多linux系统上,ALSA不能发出低延迟声音,这意味着您编写的任何最终与ALSA对话的东西也不能发出低延迟声音。如果您的系统设置为使用
esd
或其他声音守护程序(如果可能),并在必要时后退,那么您显然不希望出现这种情况。因此,如果这是您的问题,您将必须配置
SDL\u混音器
以使用不同的驱动程序


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

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

还要注意的是,
SDL_mixer
将在你的背后自动重新编码你的声音,如果它们的采样率不相同/等等。作为目标,这不仅增加了CPU工作的延迟,还意味着真正的缓冲区大小与你认为正在使用的缓冲区无关

另一种方法是使用
pygame.mixer
/
SDL\u mixer
,自己进行混音,然后直接转到
pygame.sound
/
SDL\u sound
。这仍然会有相同的驱动程序问题,但任何由
SDL\u mixer
(如重新编码)引起的问题都会消失

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


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

这显然不是你的问题,因为你所做的只是给
pygame.mixer
一个预先制作好的声音。但是,如果您决定需要(比如)将声音预转换并将缓冲区馈送到
pygame.sound
,那么您可能会遇到这样的问题:Python在循环和算术方面都很慢

我所说的“慢”是指微秒级。每20ms缓冲区循环一次不是问题。每个样本循环一次可能是错误的。如果你正在做任何处理,你应该考虑使用NUMPY或专用音频库来执行咕噜工作,而不是纯Python。 pygame是延迟的原因吗

可能不会

Pygame只是SDL的包装。在像这样的一些地区,这是一个非常薄的包装

但SDL,或者更确切地说,SDL\U混音器可能很容易成为问题

因此,您可能需要了解一下SDL,以便使用
pygame
获得超出常规游戏风格需求的音频。这是一个很好的概述,尽管它似乎有点过时


首先要考虑的是你使用的音频驱动程序。例如,在许多linux系统上,ALSA不能发出低延迟声音,这意味着您编写的任何最终与ALSA对话的东西也不能发出低延迟声音。如果您的系统设置为使用
esd
或其他声音守护程序(如果可能),并在必要时后退,那么您显然不希望出现这种情况。因此,如果这是您的问题,您将必须配置
SDL\u混音器
以使用不同的驱动程序


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

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

还要注意的是,
SDL_mixer
将在你的背后自动重新编码你的声音,如果它们的采样率不相同/等等。作为目标,这不仅增加了CPU工作的延迟,还意味着真正的缓冲区大小与你认为正在使用的缓冲区无关

另一种方法是使用
pygame.mixer
/
SDL\u mixer
,自己进行混音,然后直接转到
pygame.sound
/
SDL\u sound
。这仍然会有相同的驱动程序问题,但任何由
SDL\u mixer
(如重新编码)引起的问题都会消失

如果你不能让pygame/SDL做你想做的事情(例如,因为它在你的系统上支持的唯一驱动程序都很糟糕),你将不得不使用不同的库。wiki上有数百个链接,您还可以搜索PyPI。但是,您可能希望从另一方面开始,找到您想要使用的C音频库,然后搜索它的Python绑定。例如,pyAudio是围绕P的一个相对较薄的包装
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)