[pygame] Pygame causes ALSA underrun

1,279 views
Skip to first unread message

David Scheele

unread,
Aug 26, 2021, 3:21:48 AM8/26/21
to pygame...@seul.org
Hi there, new to the mailing list.
I'm currently misusing pygame and its mixer to create a raspberry pi script that can switch between different music playlists and play sfx on command, all without any graphics.
So far it worked perfectly but now, in reach of the finish line, I came across errors like this:

ALSA lib pcm.c:8306:(snd_pcm_recover) underrun occurred

I'm not even sure what this means. But it really hurts the audio playback. I play my music over pygame.mixer.Channel(0) and (1). I know that's not the usual way to do it but I have my reasons for using it.

I init my mixer with
pygame.mixer.pre_init(22050, -16, 2, 512)

I would like to put everything I can into getting the audio right as it is literally the only thing that matters in this project. Does anyone have any pointers what steps I could try?

Thanks!
David

BW

unread,
Aug 26, 2021, 11:48:22 AM8/26/21
to pygame...@seul.org
I had the same results with the Rpi architecture. They need to fix the
kernel and/or audio driver.

The underrun happens when you  push the CPU too hard, and the audio
device (seems to) expect there is audio data but there is none in the
audio buffer. I imagine it's a race condition that occurs when the
system is too busy, and the CPU can't keep the puny audio buffer fed.

The only thing you can do is throttle the CPU so that it never
overwhelms the system for long periods.

What is long? Maybe 1-3 seconds. But I had no way of testing it, so I
gave up on my Rpi game projects.

Thomas Kluyver

unread,
Aug 26, 2021, 12:02:12 PM8/26/21
to pygame-users
The docs for pygame.mixer.init() have this info, which seems relevant:

> The buffer argument controls the number of internal samples used in the sound mixer. The default value should work for most cases. It can be lowered to reduce latency, but sound dropout may occur. It can be raised to larger values to ensure playback never skips, but it will impose latency on sound playback. The buffer size must be a power of two (if not it is rounded up to the next nearest power of 2).


This is the argument you're setting to 512 (also the default). If I've understood correctly, it needs to prepare new data every 512 / 22050 seconds, or about 40 times per second.

Thomas

David Scheele

unread,
Aug 26, 2021, 3:58:53 PM8/26/21
to pygame...@seul.org
Ok thanks for the answers guys. I tinkered around a little.
As Thomas said, the buffer size impacts this problem.
First of all I was loading some 160mb .wav files with a length of up to 15 minutes into the channel. That obviously puts a lot of stress on the machine. When I upped the buffer size it reduced the occurrence of underruns. 1024 already helped. 2048 was also ok but 4096 put a noticeable delay on other sound effects playing, while not eliminating the underruns completely.
I've tried with smaller files and that seems to do the trick nicely. Even 120mb files of 10 minutes work fine with 2048 buffer.
So I'll guess I'll just have to cut my background music a bit shorter than I was anticipating, but that's alright :)

Thanks guys!
Reply all
Reply to author
Forward
0 new messages