Giocoso and Pipewire

The Linux audio stack is a convoluted mess!

In the beginning, Linux used OSS (the Open Sound System). This was replaced in the late 1990s by ALSA, the Advanced Linux Sound Architecture. ALSA is a kernel-level sound architecture that has no support for mixing multiple audio streams (so two programs cann't play simultaneously and one would block the other: some of us think this is what playing classical music ought to be like!) and no per-application volume control, because the kernel doesn't concern itself with the details as to what programs users might be running.

Along came PulseAudio, in the mid-2000s. It provided a wrapper around ALSA that allowed multiple programs to sound simultaneously and provided per-application volume control. It also added network audio streaming. By sitting on top of ALSA, however, PulseAudio added complexity to the sound stack and made working out why sound didn't work properly more complex, not less. It also was a high-latency layer, that made real-time audio tricky and started to fail, with jitter and dropouts, when the CPU was stressed enough.

So finally, in around 2015, PipeWire was invented. It replaces PulseAudio with a lower-latency and better real-time performance that's more immune to CPU load than PulseAudio ever was. PipeWire still sits on top of ALSA (ALSA is the kernel-level audio stuff, so both PulseAudio and PipeWire are the user-layer interface to ALSA). Amusingly, PipeWire runs a PulseAudio compatibility layer, so applications designed to run with PulseAudio can (allegedly) work seamlessly with PipeWire. I say 'amusingly' with venom because it now means you run an application and you haven't necessarily got a clue how it's talking to ALSA: it might be using the PulseAudio interface, or the PipeWire. Everything still works either way, so you're left a bit in the dark!

My music player PC (an ancient Mac Mini) runs Linux Mint. Linux Mint switched to using PipeWire as the default audio interface in the Wilma release (which is approximately late last year). I hadn't been aware of any of that… until I did a big software update the other day and things got “interesting”!

The issue is Giocoso's pause/resume functionality. Giocoso tells the process running the ffmpeg audio stream handler either to pause itself or resume itself. Under PulseAudio (or direct ALSA) doing this is not a problem: neither cared if the process was frozen or not, so resuming a frozen playback was without drama.

But PipeWire seeks to be modern and more efficient… which, of course, means it messes with the tried and true! When it detects that audio process has stalled, it suspends audio nodes to save power, marks the stream node as inactive and all its resources are freed. This poses a problem on playback resumption: the audio buffer behind the paused process will have been cleared, meaning that when the audio stream is resumed, it does so with invalid timestamps… and that manifests itself in garbled or 'scratchy' sound.

So guess what happened to my Giocoso setup after I foolishly subjected the Mac Mini in question to a recent software update? Pausing playback worked fine, but resuming it sounded like a Dalek with laryngitis had entered the room. Or maybe a Dalek attempting to sing Tristan und Isolde from the bottom of a swimming pool. It wasn't pleasant, put it that way.

Basically, the punchline is this: if your Linux distro uses PipeWire as its default audio stream handler, Giocoso's Pause/Resume is probably broken.

There is allegedly a fix. If you are able to tell PipeWire, “Do not treat a suspended audio device as being dead”, then the auto-cleanup of resources doesn't take place and the resumption of the playback should work as it used to. To do that, you need to create a new file:

~/.config/pipewire/pipewire.conf.d/99-nosuspend.conf

In that file, you type the following:

context.properties = {
  suspend-timeout-seconds = 0
}

Finally, you re-start PipeWire to get the new setting picked up and applied:

systemctl --user restart pipewire

Once these textual fixes are in-place, you'll find that Giocoso pauses and resumes cleanly once more.

This will be a problem for many modern Linux distros, because they've all been switching over to PipeWire by default quietly in recent months. The same fix should apply to them all. A new release of Giocoso will eventually be produced that applies this fix automatically, if PipeWire is detected on your system… but for now, the fix has to be applied manually.

My apologies for any inconvenience: this is what happens when the technological rug is tugged from underneath one! Giocoso development is, frankly, just a question of keeping up with what other Linux developers are… er, breaking!

Update 1: It turns out that this “fix” doesn't really work very reliably. Fiddling with the PipeWire suspend timeout doesn't appear to have fixed the garbled sound problem if the music playback is paused for a very long time (such as overnight): the resumed playback still sounds awful in that case. I shall attempt to get Giocoso working on different hardware to see if that resolves the issue, though why hardware which worked fine at the beginning of the week suddenly decides to misbehave after a software update is a bit of a mystery!

Update 2: Well, after much fiddling with other hardware, I ended up issuing the following commands on the original PC:

systemctl --user --now disable pipewire pipewire-pulse wireplumber
systemctl --user mask pipewire pipewire-pulse wireplumber

…to stop and disable pipewire. Then I issued this command:

sudo apt remove --purge pipewire pipewire-audio-client-libraries wireplumber

…to remove pipewire and PulseAudio from the Linux Mint 22 system completely. That means this PC is now going to be using ALSA directly (which Giocoso is happy doing). Finally, I issued this command:

sudo apt-mark hold pulseaudio pipewire

…to prevent Linux Mint “accidentally” re-installing either PulseAudio or PipeWire. A reboot followed at this point and, once the PC was back up, I issued the command:

aplay /usr/share/sounds/alsa/Front_Center.wav

…to directly play some sound… and heard everything just fine. The command:

aplay -l

…reassured me that the operating system could still see and enumerate audio devices correctly:

  **** List of PLAYBACK Hardware Devices ****
  card 0: HDMI [HDA Intel HDMI], device 3: HDMI 0 [HDMI 0]
    Subdevices: 1/1
    Subdevice #0: subdevice #0
  card 0: HDMI [HDA Intel HDMI], device 7: HDMI 1 [HDMI 1]
    Subdevices: 1/1
    Subdevice #0: subdevice #0
  card 0: HDMI [HDA Intel HDMI], device 8: HDMI 2 [HDMI 2]
    Subdevices: 1/1
    Subdevice #0: subdevice #0
  card 1: PCH [HDA Intel PCH], device 0: CS4208 Analog [CS4208 Analog]
    Subdevices: 1/1
    Subdevice #0: subdevice #0
  card 1: PCH [HDA Intel PCH], device 1: CS4208 Digital [CS4208 Digital]
    Subdevices: 0/1
    Subdevice #0: subdevice #0

I was thus able to configure Giocoso to use the “plughw:1,1” device (the digital, optical output) and music playback was fine. I then paused a piece of music in mid-play overnight. On waking, music playback was able to be resumed without any garbling or distortion.

The short take on this is, therefore, that Giocoso works fine with PipeWire so long as you don't pause or resume; that it works fine with PipeWire for short pauses and resumes if you set the suspend-timeout-seconds parameter; but that it does not work at all well with PipeWire if you intend to pause for lengthy periods (say, a half hour or more). My advice is therefore to run Giocoso on systems that do not have PipeWire installed at all (such as Alpine Linux); to remove it if it is installed; and to avoid even PulseAudio unless you intend to route Giocoso's playback over your home network. Use ALSA directly, as Giocoso was always intended to do, basically.

It is possible that I shall nevertheless re-write Giocoso's pause/resume functionality to avoid stopping and resuming audio playback at the per-process level. Giocoso already has a pause/resume functionality that involves launching a completely new playback process when music playback is resumed: the Giocoso Pro 'Global Resume' functionality. If that were employed as the sole pause/resume functionality, the garbled sound issue would be resolved even in the presence of PipeWire. It's a lot of work, however, and I wouldn't hold my breath!

  • blog/giocoso_and_pipewire.txt
  • Last modified: 2025/10/12 10:19
  • by hjr