2013-12-10 70 views
0

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

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

+1

是的,这是可能的。但是StackOverflow并不是一个很好的资源,可以用来请求工具和库的建议。详情请参阅help/faq。 – abarnert

+1

同时,Python维基上的[PythonInMusic](https://wiki.python.org/moin/PythonInMusic)上有一个页面。不知道它是如何最新或全面的,但肯定会链接到以不同方式绑定各种不同本机音频库的实时项目,这应该让您开始并向您展示可以完成的任务。 – abarnert

+0

是@abarnert,我完全修改了我的问题,以便针对与某些实现有关的确切问题提出精确问题(具有可重现的示例)。我希望能够避免“接近”,尤其是当我在这里看到类似的话题时:http://stackoverflow.com/questions/1448630/low-latency-audio-api-for-android?rq=1 – Basj

回答

5

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。