Improved sound quality using an external USB soundcard on Raspberry Pi

So after setting up MPD on my Raspberry Pi, I managed to get transmission daemon and NFS running. You can use about any good tutorial for this, since there are no special tricks involved – everything works just like on a normal GNU/Linux box.

However, you can’t expect a 35€ device to ship with a great DAC. I’m not really what you would call an audiophile, discussing how the new USB cable totally changed the sound characteristics, and how everything now sounds fresher, warmer, crisper whatsoever. Nevertheless, since I just didn’t like the Pi’s analog output, I ended up buying an external soundcard, an ESI Dr. Dac, which got good reviews on the net. It is a dead-simple device which features a single 3,5mm jack which is used for both the analog and optical digital out. The best part however is that it just works out of the box without any hassle. And of course, the sound is notably better than before (fresher, warmer, crisper).

All I had to do is to connect it to the Pi and remove line containing ‘snd_bcm2835‘ from /etc/modules, since I won’t need the analog output anymore. This way, the Dr. Dac automatically gets the default pulseaudio device, and MPD will use it for sound output. Yeah, that’s all, we’re done.

Unfortunately it does not seem to be that easy to convince XBMC to use the Dr. Dac for sound output. There is some kind of support for this, but it is far away from stable and made my XBMC crash. Maybe I’ll dig into this someday, but until then I’m happy with this setup. Most of the time I’m using the Raspberry Pi to listen to music, and once every two weeks or so I have to connect my amplifier directly with the Pi instead of the Dr. Dac. No, I don’t mind the sound quality when watching series.

Setting up MPD on a Raspberry PI with a RaspBMC installation


UPDATE:

Yesterday I installed RaspBMC Final. PulseAudio is now running out of the box, so you can skip the installation and setup of ALSA.
—-

Well, there are probably millions of tutorial for this, but still I decided to write down all the necessary steps to set up MPD on my “media center” at home. All this is done on a fresh install of RaspBMC RC5 / XBMC RC2, as released on the 30th of December. The steps are fairly straight-forward.

Let’s start with enabling sound output through ALSA and PulseAudio:

sudo modprobe snd_bcm2835

Furthermore we’ll add “snd_bcm2835” (without the parentheses) to /etc/modules, so it will be loaded on startup.

Then, install MPD:

sudo apt-get install mpd

Now let’s configure MPD. To do this we must edit /etc/mpd.conf. The file contains a lot of comments which explain the configuration settings in detail. I’ll go through all the things I needed to change in order to get MPD working. First, MPD needs to find the music. I keep my music on an external disk which I connect directly to the Raspberry PI. RaspBMC mounts it automagically on /media/. Hence, “music_directory” points to “/media/media-disk/Musik”.

I also want the playlists to be on this disk. Thus, “playlist_directory” is set to “/media/media-disk/Musik/playlists”.

While read-only access to the disk suffices for reading the music, if I want to save MPD playlists, I’ll need write access. RaspBMC mounts the disk with the user “pi”, with write permissions for the user’s group, but not for others. Since MPD will run with its own user called “mpd”, I changed MPDs group to “pi”. Furthermore, I want to control the daemon from other devices, so I changed “bind_to_adress” to “any”.

Last but not least you have to configure an audio output. I use PulseAudio for the moment, since it worked out of the box, but I’ll consider moving directly to ALSA if I notice performance issues. It’s as simple as it can be:

audio {
  type   "pulse"
  name   "Wohnzimmer"
}

And that’s it. The complete configuration file can be found here.

Next, I’ll configure NFS to access my media files from any device at home, and make transmission-daemon work.

 

Why you shouldn’t use boost::any (especially not in time-critical code)

In case you didn’t know, boost::any is a conveniant way to store & pass any (no shit, Sherlock!) datatype you can imagine. No one would expect that such nice things work without some overhead – however the implementation of boost::any does not seem to be the fastest around, as some tests I did today show. Luckily, I remembered a stack overflow answer to some unrelated question about boost::any, pointing out that there’s an alternative for boost::any in the boost library itself, namely boost::spirit::hold_any, being smaller, faster and providing nifty stream output operators. Back then, assuming boost itself being heavily optimised, I could not imagine that the performance difference was substantial, so I dropped the idea of using boost::spirit::hold_any, hoping that if its implementation was that good it would replace boost::any sooner or later anyways. As I learned today, this assumption is simply wrong.

Using a simple testing program I evaluated the performance of boost::any, boost::spirit::hold_any and simply casting to void* and back. Needless to say, casting around void pointers is the fastest method, but you are losing any type information whatsoever and may run into bugs which are difficult to find. However, even the difference between boost::any and boost::spirit:hold_any is almost an order of magnitude! Lesson learned: if you want to use a typesafe fire-and-forget-use-any-datatype concept, stay away from boost::any and stick with boost::spirit::hold_any – their usage is essentialy the same. If you need the last bit of speed (and you have checked using a profiler that hold_any is the thing thats slowing the code down) you may want to consider entering the minefield of void pointer casting 🙂

Stop your jibber-jabber, here’s the real data (setting 100000000 size_t values using each method to pass the argument to a function):

Method g++ g++ -O1 g++ -O2 g++ -O3
boost::any 7.29s 3.64s 3.63s 3.21
boost::spirit::hold_any 2.93s 0.93s 0.66s 0.40
void* 0.49s 0.32s 0.05s 0.05

It is crucial to mention that the comparison between the boost classes and passing void pointers is only fair when using these classes only to pass parameters to functions, and not their ability to store arbitrary data – to accomplish this using void pointers one would need additional code overhead, which would certainly slow the whole thing down. The key of this article was to compare boost::any to boost::spirit::hold_any, using the void* method to introduce some baseline maximum speed.

Last but not least, here’s the code I used to evaluate the performances: test.cpp. Remove the .doc extension – WP does not like uploading .cpp files 🙂