Аудио с низкой задержкой с Python

Когда используешь 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?

Пример применения: воспроизвести некоторые файлы.wav, когда MIDI-сообщения поступают с MIDI-клавиатуры. (Я хочу закодировать очень простой музыкальный сэмплер). Конечно, задержка будет сильно зависеть от аудиоинтерфейса (ASIO или нет ASIO и т. Д.), Но теперь я хочу проанализировать, возможна ли низкая дополнительная задержка с Python, и если да, то какие модули предпочтительнее для этой цели.

1 ответ

Является ли Pygame причиной задержки?

Возможно нет.

Pygame - это просто оболочка вокруг SDL. В некоторых областях - как эта - это очень тонкая обертка.

Но SDL - или, скорее, SDL_mixer- легко может быть проблемой.

Таким образом, вам, вероятно, нужно немного узнать о SDL, чтобы использовать pygame для аудио, выходящего за рамки обычного игрового стиля. Аудио с SDL - хороший обзор, хотя кажется немного устаревшим.


Первое, что нужно учитывать, это то, какой аудио драйвер вы используете. Например, во многих системах linux ALSA не может воспроизводить звук с низкой задержкой, а это означает, что все, что вы пишете, в конечном итоге говорит с ALSA, не может этого сделать. И если ваша система настроена на использование esd или какой-нибудь другой звуковой демон, если это возможно, и отступайте, если это необходимо, вы явно не хотите этого здесь. Итак, если что-то подобное является вашей проблемой, вам придется настроить SDL_mixer использовать другой драйвер.


Предполагая, что драйвер может справиться с этим, определенно возможно сделать звук с низкой задержкой pygame.mixer/SDL_mixer, Но это может не работать из коробки.

Первое, что вы хотите сделать, это выбрать меньший размер буфера, чем по умолчанию.

Также обратите внимание, что SDL_mixer автоматически перекодирует ваши звуки за вашей спиной, если они не имеют ту же частоту дискретизации / и т.д. поскольку цель, которая не только добавляет небольшую задержку для работы процессора, это также означает, что реальный размер буфера не имеет ничего общего с тем, который, как вы думаете, вы используете…

Альтернатива этому - обойти pygame.mixer/SDL_mixer, сделайте микширование самостоятельно и идите прямо к pygame.sound/SDL_sound, Это будет иметь те же проблемы с драйверами, но все, что вызвано SDL_mixer (как перекодирование) уходит.

Если вы не можете заставить Pygame/SDL делать то, что вам нужно (например, потому что все драйверы, которые он поддерживает в вашей системе, все отстой), вам придется использовать другую библиотеку. PythonInMusic в вики имеет сотни ссылок, и вы также можете искать PyPI. Однако вы можете начать с другой стороны - найти аудио-библиотеку C, которую вы хотите использовать, а затем найти для нее привязки Python. Например, pyAudio - это относительно тонкая оболочка для PortAudio, поэтому он выглядит так, как если бы требования Portaudio по переносимости, конфигурируемости и производительности соответствовали вашим потребностям, а его API соответствовал вашему дизайну, но в противном случае это плохо.


Другое место может пойти не так в вашем коде.

Это, очевидно, не проблема в вашем случае, потому что все, что вы делаете, это дает pygame.mixer готовый звук. Но если вы решите, что вам нужно, скажем, предварительно преобразовать звуки и буферы подачи в pygame.soundВы можете столкнуться с проблемой, что Python медленен в цикле и медленен в арифметике.

Под "медленным" я подразумеваю порядка микросекунд. Зацикливание буфера один раз в 20 мс не является проблемой. Цикл один раз на образец может быть. Если вы выполняете какую-либо обработку, вам следует подумать об использовании NumPy или выделенной звуковой библиотеки для выполнения работы, а не на чистом Python.

Другие вопросы по тегам