How to setup a bit-perfect digital audio streaming client with free software (with LTSP and MPD)

Introduction

This article describes how to create a software environment on your desktop computer which will make it possible to boot a second computer from the network and use that as the interface between the desktop computer –from which the audio files and the boot environment are served– and the external audio equipment.

The goal is to achieve maximum audio quality using low-cost off-the-shelve equipment and free software and at the same time offering ease of configuration and use. Of course this comes with a price; reading and understanding this article.

When you simply want your PC (with a locally installed mpd) act as an audiophile transport device, please have a look at the article “How to turn Music Player Daemon (mpd) into an audiophile music player”.

Background and goals

I love both music and free software.

After having used the Slimdevices Squeezebox as a streaming client connected to a MSB Link DACII (review) for seven years, I got tired with the fact that I couldn’t use any other client devices or software or formats –the squeezebox client device only outputs 16bit/44.1KHz and can only communicate with the squeezebox server software. Furthermore, my audio equipment didn’t fit my life any more (too big and THX/surround targeted).

In September 2010 I therefore bought a new audio system consisting of small and relative cheap Opera Mezza stereo speakers, the 24 bit Pink Faun USB DAC 3.24 and a Pink Faun D-Power 140 power amplifier in which the excellent engineers of Pink Faun fitted their newly developed remote controlled volume control. The speakers are connected to the amp using Pink Faun SC-4 cable, while Pink Faun IL-2SE cable is used between the amplifier and the DAC. The power and USB-cables I use are all standard cheap ones and leave room for improvement.

After buying this set I started using xbmc on a laptop which was connected to the DAC with a cheap USB cord and really loved the sound. I couldn’t wait to play native 24bit / 96KHz music. All my digital music files where flacced EAC rips of my own CD’s. I bought some 24/96 albums from HDtracks.com but the results were disappointing. After waiting for a while (to let my rather new equipment settle) I tried again with the same results. On the ergonomic side I really liked the fact that I could use my laptop both as a media controller and as sort of a black box by using whatever software client (like banshee and rhythmbox) on my desktop PC and the DLNA/upnp features of pulseaudio.

On the Internet I learned that although the input consisted of 24bit/96KHz files, the actual audio stream received by the USB-DAC was in fact down sampled to 16bit/44.1KHz by some piece of software!

My DAC doesn’t indicate which bit depth or sample rate it uses, but watch out. Even if your DAC does indicate 24bit/96KHz when playing a high resolution file, it could also do so with other formats. That is because the software is also able to upsample, using an arbitrary and bad format conversion algorithm like libsamplerate. To complicate things further, a lot of DACs try to do the same on the hardware side.

The worst case scenario is that when you play a 24bit/96KHz file, it first gets downsampled to 16bit/44.1Khz by the software –again using a fast and sloppy algorithm– and secondly gets upsampled to 24bit/96KHz by the DAC. Instead of crispy tube like sound and depth, you get a MP3 experience.

It seems the price for convenience buys you a ticket to 1990’s ideas of sound perception.

Default pulseaudio with alsa configurations perform on the fly bit depth and sample rate conversion for ensuring a pop and crackle free “plug-n-play” experience (see pulseaudio ticket #930: Media players report 96khz, proc reports 44khz and the article “Which digital audio formats does your USB DA-converter support and use?”). Most audio enthusiasts won’t be thrilled by these “qualities” and would like to leave decoding of the audio stream to (more suitable) external audio equipment like a DA-converter. Sample-rate conversion should be avoided altogether when possible. Currently, one has to bypass the default pulseaudio layer altogether and alter the default alsa configuration to get multi-format bit-perfect output to the external DAC.

In short, my wanted setup had the following requirements:

  • having bit-perfect audio for all digital formats accepted by my DAC
  • having the freedom of only using free software
  • having the freedom of only using open –non patent encumbered– file formats
  • having the freedom to use any client device as a streaming digital audio device
  • having the freedom to use any device for controlling the streaming digital audio device (acting like a “media controller”)

To achieve these goals I’ve made the following choices:

  • create a LTSP environment using my desktop PC as the LTSP server
  • installing a MPD client on the desktop PC or Android client acting as a media controller
  • using an old HP t5725 thin client as the LTSP client
  • this thin client will also act as a (headless) MPD server

The result is whopping! I can plug in any PXE-capable PC, thin client, plug computer or laptop to my LAN and connect it to my DAC with USB. After 15 seconds of booting (serving the LTSP image from a old-school SATA disk) it is a bit perfect audio streaming client. I can use any PC, laptop, tablet, smartphone or tablet to control the music player and browse through my playlists and music library.

Preparation

Step 1: Create a working LTSP-server environment

Follow the instructions to set up a LTSP server and LTSP client image using https://help.ubuntu.com/community/UbuntuLTSP/FatClients.

This process also involves installing and/or configuring DHCP and TFTP to serve the generated LTSP image to LTSP clients.

The result should be:

  • a working DHCP server which has `dhcp-boot` options filled in for PXE enabled clients
  • a working TFTP server with LTSP client boot scripts in `/var/lib/tftpboot/ltsp.i386`
  • a working LTSP fat client chroot environment in `/opt/ltsp/i386`

Step 2: Install mpd in the LTSP client chroot

Install `mpd` in the LTSP client chroot and disable the default startup scripts to prevent loading mpd at system start as a system daemon.

Open a terminal on the server using CTRL+ALT+T, become root and leave this terminal open throughout this exercise.

sudo su  # become root

Determine where you want to place files.

  • The location of the music library, which in my case consists of a directory per album containing tracks in FLAC format, is presumed to be `/srv/media/music` in this example, change it to your preference.
  • The home directory of the user that will run mpd, will store the settings and database for mpd. In this example we’ll use `/var/lib/mpd` for that purpose. Again, change this to your preference.
## still in the root terminal window on the server
export music_dir="/srv/media/music" # directory containing music files
export mpd_dir="/var/lib/mpd"       # home directory for the mpd user

Next create a system user account on the server for mpd with the proper group id and assign a random generated password to it.

## still in the root terminal window on the server
# generate a group for accessing music files and directories
export group_music="music"
getent group ${group_music} || addgroup --system ${group_music}
# generate a group for accessing the mpd home directory, its settings and database
export group_mpd="mpd"
getent group ${group_mpd} || addgroup --system ${group_mpd}
# extract the group id of the mpd group
export group_mpd_gid=$(getent group ${group_mpd} | awk -F: '{print $3}') 
# determine the name for the system account that will start mpd
user_mpd="mpd"
# create it with the proper home directory, group id and username
getent passwd ${user_mpd} || \
 adduser --system --home "${mpd_dir}" --shell /bin/bash --gid ${group_mpd_gid} ${user_mpd}
adduser ${user_mpd} audio          # make sure it can access the audio hardware
adduser ${user_mpd} ${group_music} # make sure it can access the music files 
chown -R ${user_mpd}:${group_mpd} "${mpd_dir}"   # fix permissions on the home directory
chgrp -R ${group_music} "${music_dir}"     # make audio group owner of the music dir
# assign a random generated password to the user
which pwgen || apt-get install pwgen # make sure pwgen is installed
export password=$(pwgen 7 1)         # generate 1 random password of 7 characters
echo "${user_mpd}:${password}" | chpasswd    # assign it the generated password

Finally we enter the ltsp chroot created earlier, install mpd and prevent it from being started from its init scripts when the ltsp client boots, because we’ll configure that later on.

## still in the root terminal window on the server
ltsp-chroot -c -d -p      # enter the LTSP client chroot environment on the server
apt-get install mpd       # install mpd in the chroot 
# comment the line to make sure mpd will not be started by the init scripts
sed -i 's/\(START_MPD\)/#\1/' /etc/default/mpd 
exit                      # exit the ltsp chroot (but leave the terminal screen open)
ltsp-update-image --arch i386 # update the initrd image

Step 3: disable pulseaudio for the LTSP client and make the music library accessible

Dynamic configuration of LTSP clients can be achieved by the configuration file `/var/lib/tftboot/ltsp/i386/lts.conf` on the LTSP server. Perform the following on the server to add the proper line which disables the auto configuration mechanism for redirecting pulseaudio and at the same time leave alsa intact.

Furthermore, we’ll add the proper lines to `lts.conf` to make the music directory accessible through sshfs.

## still in the root terminal window on the server
cat >> /var/lib/tftpboot/ltsp/i386/lts.conf <<EOF
SOUND = False
LOCAL_APPS = True
LOCAL_APPS_EXTRAMOUNTS = ${mpd_dir},${music_dir}
EOF

 

References:

Step 4: Prepare the user environment

One has to configure a user account on the server which will automagically logon in the LTSP client after it is booted, determine and configure the preferred sound card as exposed by the external DAC and start serving mpd on the local network.

Next, test the LTSP client environment by booting the LTSP client and logging in as the mpd user created above. If you can login and get a proper desktop, continue with the following steps.

Step 5: Download and unpack the mpd-configure script to configure alsa and mpd

Again on the server, download and unpack the mpd-configure script in  `/srv/media/mpd`. The basic example below will work if you have a single USB DAC. See the `README` file in the `./mpd-configure` directory for additional and more advanced settings.

## still in the root terminal window on the server
export dir_mpdconf="${mpd_dir}/mpd-configure" # target for the mpd-configure script
mkdir -p "${dir_mpdconf}"   # create it
cd "${dir_mpdconf}"         # change to it
# download and unpack the latest version of the script
wget https://github.com/ronalde/mpd-configure/tarball/master -O - | tar --strip-components=1 -zxf - 
# next store the settings in the file ${HOME}/mpd-configure/mpd-configure.conf 
# for easy retrieval later on.
cat >> "${dir_mpdconf}/mpd-configure.conf" <<EOF
export CONF_MPD_MUSICDIR="${music_dir}" # directory holding the msuci files
export CONF_MPD_HOMEDIR="${mpd_dir}"    # home directory for the user running mpd
export LIMIT_INTERFACE_TYPE="usb"       # limit to usb audio devices
EOF

Test the script by logging on to the LTSP client as user mpd, starting a terminal and executing the following commands. Next, examine the output and modify the settings in `mpd-configure.conf` until the following conditions are met:

  1. it shouldn’t ask questions about which audio interface you want to use
  2. The paths should match those specified earlier
## logged on to the ltsp client as user mpd
export dir_mpdconf="${HOME}/mpd-configure
bash ${dir_mpdconf}/mpd-configure

If the test above succeeds, try starting the mpd application by executing the following command (still logged on the LTSP client as the mpd user).

## still in the mpd terminal window on the client
bash ${dir_mpdconf}/mpd-configure > ${HOME}/mpd.conf # generate the mpd.conf file
/usr/bin/mpd ${HOME}/mpd.conf   # start mpd using the generated .mpdconf
ps auxwww | grep "/usr/bin/mpd" # check if the mpd process has been started

Step 6: Install a mpd client on the LTSP server

On the server you should now be able to connect to the mpd application running on the LTSP client with a mpd client like the Gnome Music Playing Client (gmpc). Execute the following on the server to install and run this application.

## back in the root terminal window on the server
add-apt-repository ppa:gmpc-trunk/mpd-trunk # add the mpd ppa to the server
apt-get update # refresh the list with available packages
apt-get install gmpc # install gmpc on the server

 

You may now start GMPC by looking for it in the starter menu on your normal desktop. In the configuration dialog which appears when you first start gmpc enter the IP address of the LTSP client in the Host section and check the option Automatically connect.

Step 7: Automate the logon process

If these tests succeed, modify `${mpd_dir}/.profile` to make sure the script above will start automagically after the mpd user logs on on the LTSP client.

# still logged on as root on the server
# modify the startup script of the user running mpd
cat >> ${mpd_dir}/.profile <<EOF
export MPD_CONF="${HOME}/mpd.conf"
/usr/bin/mpd --kill               # stop mpd if it's running
${HOME}/mpd-configure/mpd-configure > "${MPD_CONF}" && \
 /usr/bin/mpd "${MPD_CONF}"    # start mpd with the script generated config
EOF

chown -R ${user_mpd}:${group_mpd} "${mpd_dir}./profile" # fix ownership

As a final test, reboot the LTSP client and logon as the `mpd` user ; now mpd should be automatically configured and running.

Finally, modify the LTSP client configuration `/var/lib/tftboot/ltsp/i386/lts.conf` on the LTSP server. The following command adds the proper lines to make sure the user running mpd logs on automatically after starting the LTSP client.

## still in the root terminal window on the server
cat >> /var/lib/tftpboot/ltsp/i386/lts.conf <<EOF
LDM_AUTOLOGIN = True
LDM_USERNAME = ${user_mpd}
LDM_PASSWORD = ${password}
EOF

Restart the LTSP client; it now should automatically logon and start the properly configured mpd. Test it by using the gmpc on the server.

References and thoughts

Drawbacks of the setup

In this setup, one has to make sure that each audio file is properly formatted according to the DAC’s native formats.

The designer of my DAC, Matthijs de Vries, has some good reasons to limit the USB interface of the DAC to 24bit/96KHz as he explains in Dutch in his White Paper “Pink Faun DAC 2 (Oktober 2010)”.

A higher data rate theoretically provides a better output. This appears still not completely true at this time. The disadvantages of 24/192 [USB DAC’s] are:

  1. [Support for 24/192 USB-DAC’s] is only possible in the newest operating software versions, and is asynchronous. As a result, one needs to fall back on self-developed drivers, which adds another layer in the software stack. 24/96 usually works with the native drivers which are already present [in current operating systems]. The user doesn’t have to install any additional software.
  2. The electronics are much more complex with 24/192; both DSP’s and numerous operations are necessary. The cure quickly becomes worse than the problem.
  3. The sampling frequency determines the resolution bandwidth, which is around 40KHz at 96kHz sampling rate. 192 kHz only gains so much in the audible range.
  4. [Galvanic] isolation does not currently work with 24/192, at the moment, 24/96 is the maximum achievable.

The engineer is –like me– a child of the spirit of early 90’s Dutch universities. He therefore was introduced to a Microsoft dominated computer world, rather than the pre-90’s environments in which open source and Unix dominated universities. You can’t blame him that his perspective on software is Microsoft oriented. Although Microsoft tried to frustrate the further development of the USB Audio Class standard by bailing out and not developing a driver for USB Audio Class 2, fact of the matter is that asynchronous 192kHz USB Audio Class 2 is natively supported on both Linux and Mac since 2010. So his first statement is wrong.

Unfortunately my DAC doesn’t support sample rates which are a multitude of 44.1KHz, like CD (1x=44.1KHZ), DVD-audio (2x=88.2) KHz or PCM converted from DSD (64x=2822.4kHz DSD converted to 4x=176.4Khz PCM). This means that I have to resample those files using a good-as-it-gets software converter.  In my case, I choose to upsample 88.2 to 96KHz and downsample 176.4 to 96Khz using the following script using the Shibatch SRC in twopass non-fast mode algorithm.

To see how your USB DAC behaves, have a look at the article “Which digital audio formats does your USB DA-converter support and use?”.

Good luck

4 thoughts on “How to setup a bit-perfect digital audio streaming client with free software (with LTSP and MPD)

Leave a Reply

Your email address will not be published. Required fields are marked *