From c84bae739a29ec27790c5534b7fc777d6f40a02f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 17 Jan 2020 16:37:09 +0100 Subject: [PATCH] pcm/Convert: add option to enable the integer-only dsd2pcm implementation --- NEWS | 1 + doc/user.rst | 20 ++++++++++++++++++++ src/config/Option.hxx | 1 + src/config/Templates.cxx | 1 + src/pcm/Convert.cxx | 19 +++++++++++++++++++ 5 files changed, 42 insertions(+) diff --git a/NEWS b/NEWS index 21e28ee0b..efb10b604 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ ver 0.22 (not yet released) - ffmpeg: new plugin based on FFmpeg's libavfilter library - hdcd: new plugin based on FFmpeg's "af_hdcd" for HDCD playback - volume: convert S16 to S24 to preserve quality and reduce dithering noise + - dsd: add integer-only DSD to PCM converter * output - jack: add option "auto_destination_ports" - jack: report error details diff --git a/doc/user.rst b/doc/user.rst index d75975d21..73559f122 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -568,6 +568,26 @@ Sometimes, music needs to be resampled before it can be played; for example, CDs Check the :ref:`resampler_plugins` reference for a list of resamplers and how to configure them. +DSD +^^^ + +There are three ways to play back DSD (Direct Stream Digital): + +- natively if your output supports it (ALSA only and requires a sound + card with native DSD support) +- `DSD over PCM `_: wrapped + inside fake 24 bit PCM samples (ALSA and OSX only and requires an + external DAC with DoP support) +- for everything else, MPD automatically converts DSD to PCM + +For the last option, the setting ``dsd2pcm_converter`` selects a +conversion method. The default is ``float`` which converts to +floating point samples. For CPUs with a weak floating point unit +(e.g. some ARMs like the one in the Raspberry Pi), it may be faster to +use ``integer``, which is an integer-only implementation of the +conversion algorithm. + + Client Connections ------------------ diff --git a/src/config/Option.hxx b/src/config/Option.hxx index 0344b6695..f8994124e 100644 --- a/src/config/Option.hxx +++ b/src/config/Option.hxx @@ -79,6 +79,7 @@ enum class ConfigOption { DESPOTIFY_USER, DESPOTIFY_PASSWORD, DESPOTIFY_HIGH_BITRATE, + DSD2PCM_CONVERTER, MAX }; diff --git a/src/config/Templates.cxx b/src/config/Templates.cxx index 01205c3d0..48a680242 100644 --- a/src/config/Templates.cxx +++ b/src/config/Templates.cxx @@ -75,6 +75,7 @@ const ConfigTemplate config_param_templates[] = { { "despotify_user", false, true }, { "despotify_password", false, true }, { "despotify_high_bitrate", false, true }, + { "dsd2pcm_converter" }, }; static constexpr unsigned n_config_param_templates = diff --git a/src/pcm/Convert.cxx b/src/pcm/Convert.cxx index 1cfd186d8..9cc2e0cec 100644 --- a/src/pcm/Convert.cxx +++ b/src/pcm/Convert.cxx @@ -19,16 +19,35 @@ #include "Convert.hxx" #include "ConfiguredResampler.hxx" +#include "config/Data.hxx" #include "util/ConstBuffer.hxx" +#include "util/StringAPI.hxx" #include #include +#ifdef ENABLE_DSD +static bool dsd2pcm_integer = false; +#endif + void pcm_convert_global_init(const ConfigData &config) { pcm_resampler_global_init(config); + +#ifdef ENABLE_DSD + dsd2pcm_integer = config.With(ConfigOption::DSD2PCM_CONVERTER, [](const char *s){ + if (s == nullptr) + return false; + else if (StringIsEqual(s, "float")) + return false; + else if (StringIsEqual(s, "integer")) + return true; + else + throw std::runtime_error("Unrecognized value"); + }); +#endif } PcmConvert::PcmConvert(const AudioFormat _src_format,