moOde with MPD Selective Resample

Music Player Daemon is a daemon used in a lot of (Raspberry Pi) audio distributions. Including the one that I use; moOde Audio Player. MPD supports a bunch of plugins, including SoxR for high quality resampling. Which can be used for both up and down sampling.

The most common used audio sample rates are based on two ‘base’ clocks; multiplicity of 44.1 kHz or48 kHz. Typical matching sample rates:

  • 44.1 kHz based: 44.1 , 88.2, 176.4, 352.8 kHz
  • 48 kHz based: 48, 96, 192, 384 kHz

Is you resample to a different base clock, for example from 44.1 to 96 kHz, you will get a big performance penalty with SoxR. At least compared with from 48 to 96kHz. It takes twice the number of CPU resource than from 48 to 96 kHz.

In MPD you can configure a target sample rate. Lets say we configure MPD to upsample to 96kHz. This works nice for 48 and 96kHz source, only for 44.1 and 88.2 kHz the outcome is a little bit different. You can image that from 48 to 96 (ratio 2) is a lot easier than 44.1 to 96 (ratio 2.17). You Raspberry Pi agrees and is lot busier with 44.1 to 96kHz. Almost twice the number of CPU resources are used. I don’t dare to say something about the audio quality, I just focus of the used CPU resources.

Wouldn’t it be nice if the 44.1 is just upsample to the nearest round base sample rate? This is what the supplied patch will do.. You just provide the max, as specified in a 48kHz base sample rate and 44.1 based will just match to the closest (but lower) sample rate.

At the end of this articles the results of performance test are shown and includes the commands to reproduce it yourself.

Patch MPD

Please follow the updated instructions concerning patching and installation in https://github.com/bitkeeper/dddac1794build/tree/master/raspberrypi/software for MPD patch and custom settings for Moode MPD !!!

moOde only supports the resample option by using the global audio_output_format setting. Due this the patch will introduce a global setting called selective_44k_resample.

This will not work with Volumio because it doesn’t use the global resample option audio_format option, but the one on the output device. Of course the supplied patch could be changed to also support output devices.

The patch is tested with moOde 6.4.2 and mpd-0.21.20. For building the patch the easiest way is to do it directly on your target. The build instructions below are based moOde build recipe.

pi@moode:~ $ wget http://www.musicpd.org/download/mpd/0.21/mpd-0.21.20.tar.xz
pi@moode:~ $ wget https://www.bitlab.nl/wp-content/uploads/2020/04/mpd_0.21.20_selective_44k_resample.patch
pi@moode:~ $ tar xf mpd-0.21.20.tar.xz
pi@moode:~ $ cd mpd-0.21.20
pi@moode:~ $ patch -b -p1 < ../mpd_0.21.20_selective_44k_resample.patch
pi@moode:~ $ meson . output/release --buildtype=release -Db_ndebug=true
pi@moode:~ $ meson configure \
-Dalsa=enabled \
-Dbzip2=enabled \
-Dcurl=enabled \
-Ddatabase=true \
-Ddsd=true \
-Dffmpeg=enabled \
-Dfaad=enabled \
-Dflac=enabled \
-Dhttpd=true \
-Did3tag=enabled \
-Dlame=enabled \
-Dlibmpdclient=enabled \
-Dmad=enabled \
-Dmpg123=enabled \
-Dpipe=true \
-Drecorder=true \
-Dshout=enabled \
-Dsoundcloud=enabled \
-Dsoxr=enabled \
-Dvorbis=enabled \
-Dwave_encoder=true \
-Dwavpack=enabled \
-Dzeroconf=avahi \
-Dzzip=enabled \
-Dao=disabled \
-Daudiofile=disabled \
-Ddbus=disabled \
-Dexpat=disabled \
-Dfluidsynth=disabled \
-Dgme=disabled \
-Dipv6=disabled \
-Djack=disabled \
-Dlibsamplerate=disabled \
-Dnfs=disabled \
-Doss=disabled \
-Dpulse=disabled \
-Dsidplay=disabled \
-Dsmbclient=disabled \
-Dsndfile=disabled \
-Dsqlite=disabled \
-Dudisks=disabled \
-Dupnp=disabled \
-Dwildmidi=disabled \
output/release
pi@moode:~ $ ninja -C output/release

Especially the latest step will take quite some time. After the build there should be an MPD executable in the ./output/release directory.

Now we have to copy the executable to the location where the system will use it. We have to make sure it isn’t in use, else the file will be locked.

sudo killall worker.php
sudo killall watchdog.sh
sudo rm /run/worker.pid
sudo systemctl restart php7.3-fpm
sudo systemctl restart nginx
sudo systemctl stop mpd
sudo mv  /usr/local/bin/mpd /usr/local/bin/mod.orig
sudo cp output/release/mpd /usr/local/bin
sudo /var/www/command/worker.php

If you are coming from a stock Moode 6.4.2 ( with mpd-0.20.16) you need to regenerate you library, due some changes in the mpd-0.20.21 code.

Usage

To use a MPD build with the selective_44k_resample patch:

  1. Set audio_out_format to a multiplication of 48kHz like 96000:24:2 (Off course you have to make sure the target requested sample rate is supported by your output and/or DAC.).
  2. Set selective_44k_resample is set to yes.

For use with moOde the first one is clear. Open the MPD Configuration page and set the wanted resampling options.

Moode MPD config Sox Resampling configuration

The second one is a little bit harder to do. moOdedoes support small subset of the available MPD settings, let alone new settings. And because moOde generates the configuration for MPD any manual made tweaks are overwritten.

We need to make a small change to MPD configuration generator.

I use myself another patch for moOde. That patch adds the possibility to add additional global and device MPD options by using the moOde web interface. There we can just add the option selective_44k_resample "yes" to the general parameters.

Custom Moode MPD Tweaks

Search in the file /var/www/inc/playerlib.php for the following two line in the function updMpdConf. With Moode 6.4.2 the function starts at line 1521.

$data .= "max_connections \"128\"\n";   
$data .= "\n";

Insert between the two lines a new one with the content below:

$data .= "max_connections \"128\"\n"; 
$data .= "selective_44k_resample \"yes\"\n"; 
$data .= "\n";

Reboot your Pi to make sure the new code is used. After boot go the the mpd configuration page and press save to make sure the mpd configuration is generated.
To be sure you can check if the settings is in the mpd configuration by executing the following command:

cat /etc/mpd.conf| grep selective_44k_resample 
selective_44k_resample "yes"

It should return the setting with yes.

Performance tests

The test are performed with the command line version of sox.

Used test environment:

  • Pi 2B
  • Raspbian Buster Lite 10.2
  • kernel 4.19.97-v7+
  • SoX 14.4.2

Tests are run on a ramdisk. As test file the default audio from moOde is
used. To prevent testing decoder/encoders test files are wave files.

Performed tests:

  • 44.1/16 to 96/24
  • 48/16 to 96/24
  • 44.1/16 to 88.2/24

In the results below it is clearly visible that the resampling from 44.1 to 96 takes twice as more CPU resources that for 88.2 or 48 to 96.

To be able to reproduce the test yourself in the file below all commands to setup and execute the tests are in the attached file:

Test 48/16 to 96/24

pi@moodedev:/mnt/ramdisk $ perf stat sox LRMonoPhase4_48_16.wav -b 24 LRMonoPhase4_96_24.wav rate -v 96000

 Performance counter stats for 'sox LRMonoPhase4_48_16.wav -b 24 LRMonoPhase4_96_24.wav rate -v 96000':

          2,574.54 msec task-clock:u              #    0.999 CPUs utilized
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
               245      page-faults:u             #   95.183 M/sec
     2,169,128,394      cycles:u                  # 842707.224 GHz
     1,492,424,845      instructions:u            #    0.69  insn per cycle
       103,511,129      branches:u                # 40214113.831 M/sec
         2,726,871      branch-misses:u           #    2.63% of all branches

       2.577343598 seconds time elapsed

       2.436878000 seconds user
       0.140396000 seconds sys

Test 44.1/16 to 96/24

pi@moodedev:/mnt/ramdisk $ perf stat sox LRMonoPhase4_44_16.wav -b 24 LRMonoPhase4_96_24.wav rate -v 96000

 Performance counter stats for 'sox LRMonoPhase4_44_16.wav -b 24 LRMonoPhase4_96_24.wav rate -v 96000':

          5,097.92 msec task-clock:u              #    0.999 CPUs utilized
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
               309      page-faults:u             #   60.624 M/sec
     4,385,703,707      cycles:u                  # 860448.049 GHz
     2,983,902,787      instructions:u            #    0.68  insn per cycle
       316,741,603      branches:u                # 62142751.226 M/sec
        10,099,792      branch-misses:u           #    3.19% of all branches

       5.101232776 seconds time elapsed

       4.960521000 seconds user
       0.140014000 seconds sys

Test 44.1/16 to 88.2/24

pi@moodedev=/mnt/ramdisk $ perf stat sox LRMonoPhase4_44_16.wav -b 24 LRMonoPhase4_88_24.wav rate -v 88200

 Performance counter stats for 'sox LRMonoPhase4_44_16.wav -b 24 
 LRMonoPhase4_88_24.wav rate -v 88200'=

      2,385.83 msec task-clock=u       =    0.998 CPUs utilized
             0      context-switches=u =    0.000 K/sec
             0      cpu-migrations=u   =    0.000 K/sec
           243      page-faults=u      =  101.887 M/sec
 1,992,758,822      cycles=u           = 835538.290 GHz
 1,371,449,852      instructions=u     =    0.69  insn per cycle
    95,114,857      branches=u         = 39880443.187 M/sec
     2,507,847      branch-misses=u    =    2.64% of all branches

   2.389982451 seconds time elapsed

   2.248309000 seconds user
   0.139894000 seconds sys

Leave a Reply

Your email address will not be published.