Semi-Home Brew Wireless Audio Streaming

I found a great solution for streaming audio from my receiver to a mobile device. It’s called SoundWire and is composed of an app you run on your phone, and a server you run on a PC that encodes audio from any available source and sends it over the network to connected app instances. Plug the receiver into the PC’s line input and you have a great wireless headphone solution.

The server has Windows and Linux builds, but even better it has a RaspberryPi build. As a cheap low-power solution, the Pi can’t be beat. Let’s get that working.

The first problem is that only audio input on the Pi is I²S and requires another card. To heck with that; they make USB sound cards for just this reason. I chose a Diamond Multimedia XS71UV2. It’s got a stereo line input which is what I need for my application. The “card” is based on the C-Media CM6206 which is supported by the raspbian jesse distribution.

I had one hiccup with getting SoundWire server to work. After following the directions, all I got was complete silence. Sure enough pavucontrol showed no sound on the input, no matter what input option I chose. Turns out, others have had this problem. The sound card has two ports connected to the one encoder, but pavucontrol doesn’t switch them properly. You have to use the following command to do it manually:

amixer -c 1 set ‘PCM Capture Source’ ‘Line’

The next trick is to get it to start on boot. Raspbian Jesse uses systemd, which is the preferred way to start things in GNU/Linux now. I wanted to use the user instance of systemd, but SoundWire server doesn’t work properly if the network isn’t up when it starts. The best way to ensure the network is up is to add a dependency on the network and that can be done only from the system instance.

However, you can’t run pulseaudio as as root, so you need to run as a user. And if you want logging to work you need to work around a buffering limitation in the server too. And you probably want least niceness to prevent any skipping. At the end of the day you have a systemd unit that looks like this:

Assuming you named the unit soundwire.servce and you put it in /etc/systemd/system all you need to do is:

systemctl enable soundwire.service

Reboot, and you are off to the races.