PulseAudio and Networked Sound


December 14, 2015

PulseAudio is fundamental to modern linux sound architecture. Before you begin it would be extremely helpful to familiarize yourself with the PulseAudio User Documentation

Premise


I took a single desktop computer and, using Xen, created a virtual multi-machine network comprising a router/firewall, mail systems, public and private web servers, database servers, and a personal machine for my projects, music, videos, and other interests. The grand plan called for a very small host O/S isolated from the world using just enough resources to keep everything else running. The reality was that I couldn't figure out how to get audio from my personal space onto the system's hardware sound devices. I didn't even know whether it was possible without passing a different sound device, with all the complexity that would entail, through to my virtual machine.

In spite of the massive amount of information on virtualization out there there was very little that I could find when it came to audio. There were some virtualization techniques that did support audio but most of them came with a penalty: they were slow and I wanted the holy grail - bare metal.

So the grand plan turned instead into a bloated host O/S where I enjoyed my multimedia, kept up with the news, and surfed the wild and wooly web, all the while knowing that if somebody got in they had the keys to the kingdom.

I finally got some help in the way of a page showing how a Raspberry Pi could be used to provide a networked solution for audio projects. That provided enough of the pieces to get me going.

Concept


PulseAudio is extremely powerful but we're only going to deal with its most basic capability in this exercise and that is its ability to move audio from one place to another. In PulseAudio's parlance those places are called sinks and sources. Most simply, sources are the places audio comes from: microphones, line inputs, other instances of PulseAudio. Sinks are the places where audio can be sent: line outputs, hardware devices where their audio information is converted to sound, and other instances of PulseAudio.

To keep track of what PulseAudio is doing we're going to use a graphical tool called pavucontrol. On your menus it is probably called Volume Control. Kind of like the sign on the door saying "Matias Schreiber" but the person inside is "Rupert Periwinkle". (No confusion there...)

We'll be running one instance each of both pulseaudio and pavucontrol on the host machine (the one with the sound card) and on every one of the clients (virtual machines without a sound card but ones we want to be able to listen to). pavucontrol refers to the connection between those two endpoints as a tunnel.

Versions


Private Network


To keep things nice and clean we'll create a private network named "SOUND" used only for audio. Since the only machines that will be connecting to it are virtual we'll use a software ethernet device (if you want external systems to be able to connect you could use a real ethernet device). Then we create a bridge device and make our ethernet device a member of it. Any virtual machines wanting to be on that network will also have to "join" that bridge by attaching one of their ethernet devices to it when they are brought up. For simplicity's sake this nework uses static addresses.

Create the virtual ethernet device (sound)
tunctl -t sound
Create the bridge (SOUND) and attach the ethernet device to it
brctl addbr SOUND
brctl addif SOUND sound
Give the bridge an IP address. I like to keep my networks no larger than necessary. A
/29 will allow the host to have five clients. The bridge will become the host's endpoint.
ip address add 192.168.137.1/29 dev SOUND

arbitrary IP selected from one of the non-routeable ranges

Firewall - while not strictly necessary buttoning things down never hurts.
iptables -A INPUT -P DROP
iptables -A INPUT -d 192.168.137.1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -d 192.168.137.1 -p tcp -m tcp --dport 4713 -m conntrack --ctstate NEW -j ACCEPT

End Points


Host (server end)

append to /etc/pulse/default.pa

(one client)
load-module module-native-protocol-tcp auth-ip-acl=192.168.137.2
load-module module-tunnel-source-new server=192.168.137.2

repeat this pair for each guest, using their IPs, .3, .4, .5

Virtual Machine (client end)

append to /etc/pulse/default.pa


load-module module-tunnel-sink-new server=SOUND:4713

either define SOUND in /etc/hosts or use its IP instead

Testing it Out


On each end: restart pulseaudio to pick up the changes; start pavucontrol (Volume Control). On your client: start an audio stream with something like Rhythmbox or your browser showing a youtube video - anything with an audio track.

On the client's Volume Control select the Playback tab. There should now be an entry saying something like "Chromium: Playback on". Look to the far right of that. There will be a select button. If it doesn't say Tunnel to SOUND:4713 change it. PulseAudio now knows what is playing and where it should play to. If the blue audio indicator is not dancing check the Mute button on your player and the one on the Volume Control.

Select the Output Devices tab. Look for an entry saying "Tunnel to SOUND:4713". That means that PulseAudio also knows where its audio sink is. Again, the blue indicator should be dancing to the audio track. If not, check the Mute button to the right.

Now turn to the host's Volume Control and select its Playback tab. You will see an entry saying "PulseAudio: Tunnel for user@hostname". That shows that PulseAudio on the host is aware of a remote source.

At this point you should be able to enjoy audio from your virtual machines. If it's still not working you may have to log out and log back in to make sure that all your changes have been picked up and that the two instances of PulseAudio are communicating.