Home audio using HifiBerry & Raspberry Pi

In this post I’ll describe how to set up the audio system that has been doing its work happily in my living room for about a year now.

My initial requirements when I set it up were:

  • Any device should be able to connect to it (tablets, windows phone, notebook)
  • Not too expensive
  • Hackable
  • Always-On (low power usage, no noise)

Those requirements led me to a Raspberry Pi based system. Tablets and phones can connect via bluetooth to use the Raspberry’s speakers. And with MPD it becomes a headless music station.

Hardware

I initially tried the setup without a HifiBerry. Don’t make the same mistake. It is a waste of time. Without the HifiBerry the setup was mind bogglingly unstable. Audio streams would cut off randomly and resume minutes later. It was so bad that I thought the HifiBerry couldn’t possible help. Luckily I was wrong.

Software

I chose Archlinux because it’s my daily driver on the Desktop and therefore I’m familiar with it.

I won’t go into details on how to install Archlinux ARM because it’s documented somewhere on their site.

HifiBerry Setup

To use the HifiBerry instead of the built-in audio the snd-bcm2835 module has to be disabled. Edit /etc/modules-load.d/raspberrypi.conf with your favorite version of vim from:

snd-bcm2835

to

#snd-bcm2835

And in /boot/config.txt uncomment the following line:

device_tree_overlay=hifiberry-dacplus

Pulseaudio Configuration

The required packages can be installed using pacman:

pacman -S bluez bluez-utils pulseaudio pulseaudio-bluetooth screen dbus

Pulseaudio and bluez are required to connect a phone or tablet via bluetooth (A2DP).

Besides that, with pulseaudio the raspberry can also be set up as an audio sink for other (also pulseaudio enabled) computers.

The default configuration that ships with the packages under Archlinux will mostly do. Only one modification should be made in /etc/pulse/daemon.confg:

exit-idle-time = -1

Set exit-idle-time to -1. This will prevent Pulseaudio from shutting down if it has been idle for a while.

Getting Pulseaudio to play nicely with Bluez

Of course, simply installing all the required packages isn’t going to do the trick. Something always gets in the way.

Pulseaudio’s main use case is a desktop environment. It is usually launched within a dbus session (which in turn is launched if a user logs into his desktop environment).

Without this dbus session the communication between the bluetooth stack and pulseaudio won’t work correctly.

Having a desktop environment on the Raspberry would be a waste of resources. And it’s not required at all - it’s possible to create a dbus session anyway. Using the dbus-launch command and screen (tmux works too if you prefer that).

dbus-launch screen

Inside the screen session pulseaudio can be started:

pulseaudio -v --high-priority

And in another tab of screen use bluetoothctl to power on the adapter and pair the devices.

Bluetoothctl permissions

If bluetoothctl doesn’t react to any input there is another issue that need fixing.

The user doesn’t have the required permissions. To fix that add the user to the lp group:

usermod -a lp

And add the following in /etc/dbus-1/system.d/bluetooth.conf between <busconfig> and </busconfig>:

<!-- allow users of lp group (printing subsystem) to
   communicate with bluetoothd -->
<policy group="lp">
    <allow send_destination="org.bluez"/>
    <allow own="org.bluez"/>
    <allow send_interface="org.bluez.Agent1"/>
    <allow send_interface="org.bluez.MediaEndpoint1"/>
    <allow send_interface="org.bluez.MediaPlayer1"/>
    <allow send_interface="org.bluez.ThermometerWatcher1"/>
    <allow send_interface="org.bluez.AlertAgent1"/>
    <allow send_interface="org.bluez.Profile1"/>
    <allow send_interface="org.bluez.HeartRateWatcher1"/>
    <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
    <allow send_interface="org.bluez.GattCharacteristic1"/>
    <allow send_interface="org.bluez.GattDescriptor1"/>
    <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
    <allow send_interface="org.freedesktop.DBus.Properties"/>
</policy>

Other minor troubles along the way

  • Audio quality might be bad if the volume in alsamixer is set to 100. Fire up alsamixer and turn it down.

Enjoy

With this it should be possible to pair devices using bluetoothctl and have them play music on the Raspberry’s speakers.

To get the most out of the setup it makes sense to also install MPD or Mopidy but this is out of scope for this post.

(And once everything else is running, installing one of those two is should be straight forward anyway)

Tuesday, March 1, 2016 » Linux