Shoestring & bubblegum sound server
Thursday, 1 Mar 2012 [Monday, 19 Mar 2012]
In which I beat MacGyver. — I recently had need to play sound on a headless Linux machine. I started looking into sound servers, but everything I found seemed a significant amount of work to set up. I tried to reduce the problem to the fundamental parts involved, and by a trail of hints winding through a narrow mountain pass arrived at a rather… minimalist solution to fit my minimalist needs. I did not require anything else than to be able to hear sound at all and the solution did not require anything else of me than ALSA – and it’s hard to install a Linux machine without ALSA these days.
The entirety of the charade amounts to this:
-
On the speakerless machine, load the loopback ALSA driver:
modprobe snd-aloop index=0 pcm_substreams=1
The driver provides a card with two sound devices, and when sound is output onto a stream on one device then the driver mirrors that as an input available on the same stream on the other device.
-
Configure sound with an
.asoundrc
like this:pcm.!default { type dmix slave.pcm "hw:Loopback,0,0" } pcm.loop { type plug slave.pcm "hw:Loopback,1,0" }
This has programs default to outputting sound to stream 0 of device 0 of the loopback (pseudo-)card, and has ALSA mixing their outputs together (
type dmix
). The loopback driver will make the resulting sound available for sampling via stream 0 of device 1, for which the configuration sets up another source called loop as a simple alias (type plug
). -
On the machine with speakers you can then you can do this:
ssh -C speakerless sox -q -t alsa loop -t wav -b 24 -r 48k - | play -q -
The bolded portion configures sox’s input to use the ALSA type, and the underlined part (which is where normally a filename is given) gives name of the source – the loop alias from the configuration above. The rest of the switches tell sox to output 24-bit, 48 kHz WAV to standard output, to be picked up by ssh.
Now play something on the speakerless machine.
This will push a constant stream of sample data down the wire, even during silence; with SSH compression enabled as it is here, that will come to something like 4 KB/sec and will very slightly busy the CPU on both machines. Both resource drains stop if you break the SSH connection. You can do so at all times without sound-playing programs on the speakerless machine ever noticing.
The one and only real drawback is a playback latency of a few fractions of a second – enough to be noticably not in real time.
But as I said, I had minimal needs of it.
[Update: added explanations.]