2013-12-10 174 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。