If you want to have different programs sending their output to the same sound card (like the HiFiBerry DAC+) on the Raspberry Pi you might run into problem. The I2S sound system allows only exclusive access to the sound subsystem. The solution for this and some other issues is PulseAudio. It creates an additional abstraction layer that allows different sound sources to use is simultaneously.
Installing Pulseaudio
unfortunately the Raspbian pulseaudio package does not include some resamplers. I was not able to use the “ffmpeg” resampler with it. Therefore I decided to build my own pulseaudio package. This also allows to use PulseAudio 5 instead of version 2 that it part of the Raspbian distribution.
Note that you need to install a lot of prerequisites before you start to configure and compile pulseaudio:
sudo apt-get install -y libltdl-dev libsamplerate0-dev libsndfile1-dev libglib2.0-dev libasound2-dev libavahi-client-dev libspeexdsp-dev liborc-0.4-dev libbluetooth-dev intltool libtdb-dev libssl-dev libudev-dev libjson0-dev bluez-firmware bluez-utils libbluetooth-dev bluez-alsa libsbc-dev libcap-dev
This will install not only these packages, but also a lot of dependencies. Note that I did not install the X11 headers as Pulseaudio will run in systems mode.
Now you can get, extract, configure pulseaudio.
wget http://www.freedesktop.org/software/pulseaudio/releases/pulseaudio-5.0.tar.xz unxz pulseaudio-5.0.tar.xz tar xvf pulseaudio-5.0.tar cd pulseaudio-5.0 ./configure
Now check the output of teh configuration process. It will look like this:
prefix: /usr/local sysconfdir: ${prefix}/etc localstatedir: ${prefix}/var modlibexecdir: ${exec_prefix}/lib/pulse-5.0/modules System Runtime Path: /usr/local/var/run/pulse System State Path: /usr/local/var/lib/pulse System Config Path: /usr/local/var/lib/pulse Compiler: gcc -std=gnu99 CFLAGS: -g -O2 -Wall -W -Wextra -pipe -Wno-long-long -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing -Wwrite-strings -Wno-unused-parameter -ffast-math -fno-common -fdiagnostics-show-option CPPFLAGS: -DFASTPATH -D_FORTIFY_SOURCE=2 LIBS: -lcap -lrt -ldl -lm Enable X11: no Enable OSS Output: yes Enable OSS Wrapper: yes Enable EsounD: yes Enable Alsa: yes Enable CoreAudio: no Enable Solaris: no Enable WaveOut: no Enable GLib 2.0: yes Enable Gtk+ 3.0: no Enable GConf: no Enable Avahi: yes Enable Jack: no Enable Async DNS: no Enable LIRC: no Enable Xen PV driver: no Enable D-Bus: yes Enable BlueZ 4: yes Enable BlueZ 5: yes Enable udev: yes Enable HAL->udev compat: yes Enable systemd login: no Enable systemd journal: no Enable TCP Wrappers: no Enable libsamplerate: yes Enable IPv6: yes Enable OpenSSL (for Airtunes): yes Enable fftw: no Enable orc: yes Enable Adrian echo canceller: yes Enable speex (resampler, AEC): yes Enable WebRTC echo canceller: no Enable gcov coverage: no Enable unit tests: no Database tdb: yes gdbm: no simple database: no System User: pulse System Group: pulse Access Group: pulse-access Enable per-user EsounD socket: yes Force preopen: no Preopened modules: all Legacy Database Entry Support: yes
Make sure you have everything that you need compiled in. The alsa-module is the most important, but you will also need at least libsamplerate.
Now compile and install pulseaudio.
make sudo make install
It will be installed to /usr/local. If you compile it at the Raspberry Pi, you have some time for a coffee. Crosscompiling on a PC is much faster, but also much more complicated, therefore I would not recommend this.
Module configuration
I would recommend to start with a minimal set of modules:
#!/usr/bin/pulseaudio -nF load-module module-alsa-card load-module module-native-protocol-unix auth-anonymous=1 load-module module-always-sink
Now start Pulseaudio:
/usr/local/bin/pulseaudio -vvv --system --disallow-exit --disallow-module-loading=1 --high-priority
Pulseaudio will run in foreground. This has to be changed later, but it makes debugging much easier.
Test
I usually use mplayer with some test .wav and .flac files like this:
pi@raspberrypi ~ $ mplayer ./test-44.wav MPlayer svn r34540 (Debian), built with gcc-4.6 (C) 2000-2012 MPlayer Team mplayer: could not connect to socket mplayer: No such file or directory Failed to open LIRC support. You will not be able to use your remote control. Playing ./test-44.wav. libavformat version 53.21.1 (external) Mismatching header version 53.19.0 Audio only file format detected. Load subtitles in ./ ========================================================================== Opening audio decoder: [pcm] Uncompressed PCM audio decoder AUDIO: 44100 Hz, 2 ch, s16le, 1411.2 kbit/100.00% (ratio: 176400->176400) Selected audio codec: [pcm] afm: pcm (Uncompressed PCM) ========================================================================== AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample) Video: no video Starting playback... A: 35.0 (34.9) of 60.0 (01:00.0) 3.9%
Have a look at the output. If Pulseaudio is working correctly, you will see the AO: [pulse] as output device.
Resampling
However there are some issues, the major one is resampling. To make sure that different sound sources can be mixed all have to be synchronized to a common sample rate. This is not a big problem if you use only 44.1 and 48kHz, but if you also want to playback high-resolution music you will run into trouble with the Raspberry Pi. What is the reason for this? The biggest issue is that the Raspberry Pi CPU is not very powerful and resampling is a relatively complex procedure.
If you read about this issue on several pages on the Internet, many people suggest to use the “trivial” resampling method. It does not need a lot of calculations and therefore works on the Raspberry Pi without a lot of problems. However how trivial is trivial? Have a look at this sine wave:
My audio analyzer shows almost 3% distortions! This is not a good method to use if you’re interested in high-quality audio.
Ok, let’s look at other resamplers. The “src-sinc-…” resamplers are too complex. Even the “src-sinc-fastest” is too complex for 192kHz material.
The “src-zero-order-hold” resampler performs as bad as “trivial”.
The two resamplers that perform quite well are “src-linear” and “ffmpeg”. While distortions are a bit less with “src-linear”, “ffmpeg” used less CPU. As distortions are still quite low with “ffmpeg” I recommend this for resampling.
Upsampling or downsampling?
Ok, we found a resampler that works. But what should be the target sample rate? Down to 44.1 or 48kHz or up to 192kHz? Some people will argue that frequencies above 20kHz are not audible and therefore 44.1kHz or 48kHz are enough. While I don’t want to discuss pros and cons of high-resolution audio format here, there are some other details to think about.
With a sound card like the HiFiBerry DAC+, the clocks are generated from the Raspberry Pi. This works quite well, but different sample rates provide better clocks to the DAC than others. The DAC shows the best performance at higher sample rates. Therefore the distortions will be lower with upsampling to 192kHz than with downsampling to 44.1kHz. There is also another effect: Playback of lower sample rates does not need a lot of processing. There is more processing possible than with 192kHz material. Playing back 192kHz material with its native sample rate does not need resampling. This balances processing power between the playback software and Pulseaudio.
Configuration
My daemon.conf configuration file now looks like this:
resample-method = ffmpeg enable-remixing = no enable-lfe-remixing = no default-sample-format = s32le default-sample-rate = 192000 alternate-sample-rate = 176000 default-sample-channels = 2
All other settings use the defaults.
Conclusion
Setting up Pulseaudio on the Raspberry Pi with support for high-resolution sound formats is not trivial. However by using the right sample rates and the right resampler, it will perform well even on the Raspberry Pi. With the configuration shown here Pulseaudio uses about 50% CPU when playing back 44.1, 48kHz and 96kHz material and 20% during playback of 192kHz streams.
Hey — thanks for the guide! I’d like to mention, that I’d had to apt-get install libcap-dev. Otherwise ./configure would give me “sys/capability.h not found”
I copied original system.pa for a backup and put your minimal modules in. (in /usr/local/etc/pulse/)
When I try to start pulseaudio, I get an error: “/usr/local/bin/pulseaudio: error while loading shared libraries: libpulsecore-5.0.so: cannot open shared object file: No such file or directory”
Do you know how to resolv this?
Check your library path, setting LD_LIBRARY_PATH might help
It did! thank you!
how do i change my library path please?
Why not juste RaspBian testing to get an updated PulseAudio ?
I’m having good results setting the resampler to ‘speex-float-8’. This also allows resampling a bluetooth A2DP source (with SBC codec), which ffmpeg doesn’t (at least not for me). I’m using a Raspberry Pi B+ running Arch Linux ARM (which I recommend over Raspbian). It has the latest PulseAudio.
The ./configure says libsamplerate is not enabled while apt-get says it and its dev package are installed and up to date. Do you know what I could try to get it enabled for pulse?
appears to be deprecated: http://www.freedesktop.org/wiki/Software/PulseAudio/Notes/6.0/
well, I’ll try to get it running with the speex first and improve on it later
Pingback: Hi-Fi mit Raspberry Pi, HifiBerry DAC+ und PulseAudio [iz]