SPDIF Optical Keepalive with Pipewire
For years, I’ve run a set of Logitech Z-5500 speakers into an optical port on my PC. It gives good quality 5.1 audio, and supports AC3 + DTS digital passthrough as well as 44, 48, and 96khz bitrates.
The problem is, the speakers go into a ‘sleep’ mode where it takes nearly a second to bring the amp back online to play audio - so notification sounds are often not played at all.
To correct this, in the past, I’ve run a simple systemd service using sox to output a sine wave that is below the audible level like so: /usr/bin/play -q -n -c2 synth sin gain -95
Now however, we can do this directly within pipewire itself.
Firstly, we need to identify the output device using pw-top
. Play some audio, and look for which sink it is being played on - eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME
S 28 0 0 --- --- --- --- 0 Dummy-Driver
S 29 0 0 --- --- --- --- 0 Freewheel-Driver
S 36 0 0 --- --- --- --- 0 Midi-Bridge
S 42 0 0 --- --- --- --- 0 alsa_output.usb-Kingston_HyperX_Cloud_Stinger_Core_Wireless___7.1_000000000000-00.analog-stereo
S 49 0 0 --- --- --- --- 0 alsa_input.usb-Kingston_HyperX_Cloud_Stinger_Core_Wireless___7.1_000000000000-00.mono-fallback
R 40 1024 48000 32.3us 4.3us 0.00 0.00 0 S16LE 2 48000 alsa_output.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_3__sink
R 106 1024 48000 20.5us 5.1us 0.00 0.00 0 F32LE 2 48000 + Brave
S 50 0 0 --- --- --- --- 0 alsa_output.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_1__sink
S 51 0 0 --- --- --- --- 0 alsa_output.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio__sink
S 52 0 0 --- --- --- --- 0 alsa_input.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_2__source
S 53 0 0 --- --- --- --- 0 alsa_input.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_1__source
S 54 0 0 --- --- --- --- 0 alsa_output.pci-0000_2f_00.1.hdmi-stereo
In my case, the audio device is alsa_output.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_3__sink
.
Now we create a file at ~/.config/wireplumber/main.lua.d/spdif-noise.lua
with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
rule = {
matches = {
{
{ "node.name", "matches", "alsa_output.usb-Generic_USB_Audio-00.HiFi_5_1__hw_Audio_3__sink" }
},
},
apply_properties = {
["dither.noise"] = 2,
["node.pause-on-idle"] = false,
["session.suspend-timeout-seconds"] = 0
}
}
table.insert(alsa_monitor.rules,rule)
You’ll need to swap the name
Restart pipewire now: systemctl --user restart pipewire.service
.
Now, when your first sound plays, pipewire will continue to output sub-audible noise to keep everything alive - which is a much better solution than using sox!