Skip to content

fix: enlarge target fill level of the pulseaudio playback buffer#59

Open
me-teorick wants to merge 1 commit intohgaiser:mainfrom
me-teorick:fix/no-audio-in-waydroid
Open

fix: enlarge target fill level of the pulseaudio playback buffer#59
me-teorick wants to merge 1 commit intohgaiser:mainfrom
me-teorick:fix/no-audio-in-waydroid

Conversation

@me-teorick
Copy link
Copy Markdown
Contributor

Fixes #58

The Waydroid audio HAL requires ~10-20ms to respond to PulseAudio's PA_COMMAND_REQUEST events. Moonshine's default target fill level of the pulseaudio playback buffer (target_length) of 20ms was insufficient - the buffer would drain to zero before the audio HAL could respond to requests.

Timeline of failure:

0ms  - Audio HAL connects, writes 8,188 bytes
5-25ms - Buffer drains at 960 bytes/5ms, no requests sent yet
30ms - First PA_REQUEST sent (1,668 bytes needed)
35-40ms - Audio HAL still hasn't responded
45ms - Buffer empty, underrun occurs

After the buffer underrun occurs, sound stops working for the remainder of the streaming session. Some video playing apps freeze (waiting for sound to sync with image), other apps (notably VLC and Chrome) play silently.

The solution was to set a higher value for target_length. The new value of 60ms was determined by iterative testing of 10ms increments from the initial value of 20ms. Several tests where performed where video playing apps played correctly with sound for over one hour without any freezes or sound cuts.

Copy link
Copy Markdown
Owner

@hgaiser hgaiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting issue! It's difficult for me to test, so I'll have to take your word for it :).

.target_length
.next_multiple_of(attr.minimum_request_length)
.max(len_10ms)
.max(len_10ms * 6)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this fix still work for you if this else case is not changed? It feels strange to change the target length if there was an explicit target length requested. The default one above is semi-arbitrary, so changing it to 60msec seems fine to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I logged this some time ago, and waydroid requests target_length=4096 if I'm not mistaken, which is less than what it needs to function properly. But it does function properly when using the host's pulseaudio. So the else block is executed and the change is needed.
(I must admit that I don't fully understand that bit of code, to me it looks like the parameters that should be passed to .min() are passed to .max() and vice-versa).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any idea why it functions using the host's pulseaudio? That suggests to me we're missing some feature in our pulseaudio handling.

@hgaiser hgaiser force-pushed the main branch 2 times, most recently from 5edfd95 to d914f12 Compare April 11, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Streaming session with waydroid plays one (and only one) sound

2 participants