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.
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
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
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.
To use a MPD build with the selective_44k_resample patch:
audio_out_formatto 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.).
selective_44k_resampleis set to
For use with moOde the first one is clear. Open the MPD Configuration page and set the wanted resampling options.
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.
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.
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.
- 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