Many people prefer the simplicity of Linux ALSA over additional layers like PulseAudio or JACK. This short how-to guide shows how to add the feature of remote audio over the network on a these systems. As developer of the trx software I'm frequently asked if I have instructions on how to use it for desktop audio, and this guide is in answer to that. The requirements are:
I'll explain such a setup here. This is how I have used use my laptop to send a full mix of the desktop audio (from Firefox, mplayer etc.) in realtime to a separate PC connected to a hi-fi system. I can switch or re-route audio without re-starting applications, and this is my favoured way for on-line listening like Soundcloud.
$ scc local # send audio to local speakers $ scc box # send audio to the host 'box' $ scc none # switch off audio
We're going to do real-time routing of audio in userland. You'll need the following software:
ALSA provides a 'loopback' device via the snd-aloop kernel module. This is going to act as the hub of audio from our desktop and onward to its destination. When JACK or PulseAudio are used they fulfil this role, whereas we're going to do it using ALSA itself.
First, load the kernel module:
$ su # modprobe snd-aloop
Now we have a dummy soundcard which we can refer to as hw:Loopback,0. A quick test of it should show audio playing in realtime (but you won't be able to hear it):
$ aplay -vv -D hw:Loopback,0 test.wav
The loopback device is different to a dummy device in ALSA useland and as a kernel module it is able to provide its own clock to the applications which connect to it.
Now we feed our desktop audio into our loopback device. Add the following to your own (not root's) $HOME/.asoundrc file:
pcm.!default { type plug slave.pcm { type dmix ipc_key 2867 slave { pcm "hw:Loopback,0,0" rate 48000 format S16_LE channels 2 period_size 1024 buffer_size 8192 } } }
You can adjust some of the parameters to taste, but be aware that the Opus codec (which we'll be using in a moment) doesn't support 44100Hz sample rate.
Until now, this is very similar to almost any ALSA-based desktop audio. The difference is our use of the loopback device instead of real hardware, which we can now relay to a destination of our choosing.
First, test our loopback device is working. Play some audio to the default soundcard using your chosen desktop application, or a simple command:
$ aplay -vv test.wav
You won't hear anything to begin with; the audio is not routed anywhere. Let's tap into our audio and play it out through the soundcard:
$ alsaloop -C hw:Loopback,1,0 -P hw:0
Substitute hw:0 for whatever your hardware audio interface is.
There is one complication we need to solve; the loopback audio device takes its sample rate and format from the first audio to connect to it (whether sending or receiving.) This can quickly become unpredictable and confusing to debug. Imagine the scenario where our dmix device is not operating yet as no application is playing sound, but we run alsaloop; the loopback device will now be set up with one format (prehaps governed by the audio interface itself). This may prevent the dmix device from connecting to it, usually with a confusing and obscure error message, or none at all.
To avoid this we create a plug to read from the loopback device at a fixed format, which is an exact match for the dmix device on the other side. Add the following to $HOME/.asoundrc:
pcm.hubcap { type plug slave { pcm "hw:Loopback,1,0" rate 48000 format S16_LE } }
This new 'hubcap' device is the one we will always use to capture the desktop audio, so the command for routing to the speakers becomes:
$ alsaloop -C hubcap -P hw:0
Finally, the most useful and probably the easiest part. With these components we can use trx to send and receive the audio just like any live source.
In this example I'm going to send audio to a host called 'box'. On that host, get ready to receive audio.
$ ssh box box$ rx
Now let's send the desktop audio to that host:
$ tx -d hub -m 2 -h box
Note that we're using a small buffer size (the -m flag) here to reduce any unnecessary delay and get audio onto the network as soon as possible.
And there you have it! Remote audio over a wifi or ethernet network, running with a healthy Opus codec. Now all that's left is to tidy this setup into a something easy to configure and switch.
Here's a link to a short shell script which implements the information in this guide to optionally routes the audio locally or to another host. Now it's just a case of using:
$ scc box
to send audio to the host 'box' in the background, or
$ scc local
to switch to using the local audio interface or speakers. No re-starting of applications is necessary.
Thanks for reading. Hopefully this short explaination will get you started with some of the more advanced ALSA routing that is possible. This guide is based on my setup which I've been using for many years now, but there could easily be mistakes or corrections in this explanation so let me know if something isn't correct. Feel free to send any feedback by email.