Repository navigation
audio: [audio] host picks the host audio system; PulseAudio on request (needs testing) - #220
Merged
Merged
Conversation
`[audio] host` (`--audio-host`): "default" keeps each platform's usual host (CoreAudio, WASAPI, and ALSA on Linux, as before); "alsa"; "pulseaudio" plays through cpal's own PulseAudio client, which PipeWire answers too through pipewire-pulse, and falls back to ALSA when no server answers. The client is cpal's `pulseaudio` feature, pure Rust over the server's socket: the build links nothing new. Why: on some Linux setups cpal's ALSA backend spins a whole core. In a Debian 12 arm64 VM its worker returned from poll() about five million times a second (the descriptor stays ready while avail < avail_min), through PipeWire's ALSA plugin and the card's own device alike, while aplay with the same sizes slept. The starved emulator underran constantly, and an IP28 once sat in its power-on diagnostics. The PulseAudio client played the same stream on 0.01 s of CPU in 5 s. The default stays ALSA until that is confirmed on real hardware. The feature makes cpal's own default_host() prefer PulseAudio whenever its socket exists, so HAL2 now picks the host by id (output_host). `[audio] cpal_buffer_frames` was parsed but never reached HAL2 (HPC3 dropped the config); it now sets the host buffer size, falling back to the host's default if the device refuses it. Unset, PulseAudio gets a 512-frame period (cpal targets two, ~21 ms at 48 kHz) instead of its own default target of about two seconds, which made IRIX's sound arrive that late. `prebuf_ms` is still not used. iris-gui: a Host audio choice in the Audio section, on Linux. Docs: FEATURES.md, HELP.md, iris.toml, docs/hal2.md, CHANGELOG, rules/testing/cpal-alsa-busy-poll.md. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Needs testing on more Linux setups. Tested only on Debian 12 arm64 in a Parallels VM (PipeWire). Nothing changes unless you ask for it: the default host is still ALSA on Linux, and every other platform is untouched.
What changes
[audio] host(and--audio-host):"default"(the platform's usual host: CoreAudio, WASAPI, and ALSA on Linux, as before),"alsa", or"pulseaudio", a new opt-in on Linux. It plays through cpal's own PulseAudio client, which PipeWire answers too through pipewire-pulse, and falls back to ALSA when no server answers. That client is cpal'spulseaudiofeature: pure Rust over the server's socket, so the build links nothing new (checked: the Linux binary links only libasound). iris-gui gets a matching "Host audio" choice in the Audio section, shown on Linux only.default_host()would prefer PulseAudio whenever its socket exists, so HAL2 now picks the host by id (output_hostinsrc/dev/hal2.rs). That's what keeps ALSA the default.[audio] cpal_buffer_framesnow works. It was parsed and shown in iris-gui but never reached HAL2 (HPC3 dropped the config). It now sets the host buffer size, and a size the device refuses falls back to the host's default. When it's unset, PulseAudio gets a 512-frame period (cpal targets two, ~21 ms at 48 kHz). PulseAudio's own default target is about two seconds, which made IRIX's sound arrive that late.prebuf_msis still unused, and the docs now say so.rules/testing/cpal-alsa-busy-poll.md.Why
On this VM, cpal's ALSA backend spins a whole core: its worker returns from
poll()about five million times a second, because the descriptor stays ready whileavail < avail_min. That happens through PipeWire's ALSA plugin and on the card's own device alike, whileaplaywith the same sizes sleeps. The starved emulator underruns constantly, and an IP28 once stayed in its power-on diagnostics with the red LED lit. Through PulseAudio the same stream used 0.01 s of CPU in 5 s.I have not reproduced the ALSA spin on bare metal, so ALSA stays the default. If it turns up elsewhere (and once it's reported to cpal), ALSA could become the fallback only.
Measured
Debian 12 arm64 VM (4 vCPUs), IP28 + Max IMPACT, IRIX 6.5.22; a demo's synthesized score played for 30 s, HAL2 output captured:
host = "pulseaudio"cpal_alsa_out101% of a corePulseAudio removes the spinning thread and the stream errors, but on a 4-vCPU VM the dropouts stay. They aren't the host audio this time: HAL2's ring runs dry because the emulator itself is starved, mostly by
hptimer, which spins a core on every machine iris emulates (HAL2 paces each channel at 4 kHz and the 8254 runs at 1 kHz). A separate, not yet submitted change that letshptimersleep took the same run to 1.5 dropouts/s (26 ms lost/s) together with this one. On a host with spare cores this PR's part matters less, and on one short of cores both are needed.CI-equivalent run (Ubuntu 24.04 container with CI's packages): workspace builds,
cargo test --workspacepasses (1031 lib tests, including a new[audio] hostconfig test), and thelightning,gpujit,jitv2build works. The Mac builds unchanged, iris-gui included.Wanted
Testing on other Linux machines, especially bare metal with a plain PulseAudio server and with PipeWire. For each, it'd help to know: does
host = "pulseaudio"play cleanly, and does the default (ALSA) show acpal_alsa_outthread near 100% intop -H?🤖 Generated with Claude Code