diff options
author | Chase Geigle <geigle1@illinois.edu> | 2014-01-21 12:34:06 -0600 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-01-21 20:35:26 +0100 |
commit | 716bdc36fd5427c8e24589a00d90d47d99c81cd6 (patch) | |
tree | 16f4aeb088c29ee3cc4350cbccefccceba3f26af | |
parent | 4f120f371474dbdc3e7ec4182d257dc9492d827b (diff) | |
download | mpd-716bdc36fd5427c8e24589a00d90d47d99c81cd6.tar.gz mpd-716bdc36fd5427c8e24589a00d90d47d99c81cd6.tar.xz mpd-716bdc36fd5427c8e24589a00d90d47d99c81cd6.zip |
pcm/SoxrResampler: Add configurable quality levels
-rw-r--r-- | doc/user.xml | 39 | ||||
-rw-r--r-- | src/pcm/ConfiguredResampler.cxx | 4 | ||||
-rw-r--r-- | src/pcm/SoxrResampler.cxx | 69 | ||||
-rw-r--r-- | src/pcm/SoxrResampler.hxx | 3 |
4 files changed, 111 insertions, 4 deletions
diff --git a/doc/user.xml b/doc/user.xml index a49f025b2..c78ffcf20 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -700,10 +700,47 @@ systemctl start mpd.socket</programlisting> <row> <entry> + "<parameter>soxr very high</parameter>" + </entry> + <entry> + Use libsoxr with "Very High Quality" setting. + </entry> + </row> + + <row> + <entry> + "<parameter>soxr high</parameter>" or "<parameter>soxr</parameter>" </entry> <entry> - Use libsoxr. + Use libsoxr with "High Quality" setting. + </entry> + </row> + + <row> + <entry> + "<parameter>soxr medium</parameter>" + </entry> + <entry> + Use libsoxr with "Medium Quality" setting. + </entry> + </row> + + <row> + <entry> + "<parameter>soxr low</parameter>" + </entry> + <entry> + Use libsoxr with "Low Quality" setting. + </entry> + </row> + + <row> + <entry> + "<parameter>soxr quick</parameter>" + </entry> + <entry> + Use libsoxr with "Quick" setting. </entry> </row> diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx index 7f64e2889..a9429ef37 100644 --- a/src/pcm/ConfiguredResampler.cxx +++ b/src/pcm/ConfiguredResampler.cxx @@ -59,9 +59,9 @@ pcm_resampler_global_init(Error &error) return true; #ifdef HAVE_SOXR - if (strcmp(converter, "soxr") == 0) { + if (memcmp(converter, "soxr", 4) == 0) { selected_resampler = SelectedResampler::SOXR; - return true; + return pcm_resample_soxr_global_init(converter, error); } #endif diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx index 99277fac7..2508e816e 100644 --- a/src/pcm/SoxrResampler.cxx +++ b/src/pcm/SoxrResampler.cxx @@ -31,6 +31,72 @@ static constexpr Domain soxr_domain("soxr"); +static unsigned long soxr_quality_recipe = SOXR_HQ; + +static const char * +soxr_quality_name(unsigned long recipe) +{ + switch (recipe) { + case SOXR_VHQ: + return "Very High Quality"; + case SOXR_HQ: + return "High Quality"; + case SOXR_MQ: + return "Medium Quality"; + case SOXR_LQ: + return "Low Quality"; + case SOXR_QQ: + return "Quick"; + } + + gcc_unreachable(); +} + +static bool +soxr_parse_converter(const char *converter) +{ + assert(converter != nullptr); + + assert(memcmp(converter, "soxr", 4) == 0); + if (converter[4] == '\0') + return true; + if (converter[4] != ' ') + return false; + + // converter example is "soxr very high", we want the "very high" part + const char *quality = converter + 5; + if (strcmp(quality, "very high") == 0) + soxr_quality_recipe = SOXR_VHQ; + else if (strcmp(quality, "high") == 0) + soxr_quality_recipe = SOXR_HQ; + else if (strcmp(quality, "medium") == 0) + soxr_quality_recipe = SOXR_MQ; + else if (strcmp(quality, "low") == 0) + soxr_quality_recipe = SOXR_LQ; + else if (strcmp(quality, "quick") == 0) + soxr_quality_recipe = SOXR_QQ; + else + return false; + + return true; +} + +bool +pcm_resample_soxr_global_init(const char *converter, Error &error) +{ + if (!soxr_parse_converter(converter)) { + error.Format(soxr_domain, + "unknown samplerate converter '%s'", converter); + return false; + } + + FormatDebug(soxr_domain, + "soxr converter '%s'", + soxr_quality_name(soxr_quality_recipe)); + + return true; +} + AudioFormat SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, Error &error) @@ -39,9 +105,10 @@ SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate, assert(audio_valid_sample_rate(new_sample_rate)); soxr_error_t e; + soxr_quality_spec_t quality = soxr_quality_spec(soxr_quality_recipe, 0); soxr = soxr_create(af.sample_rate, new_sample_rate, af.channels, &e, - nullptr, nullptr, nullptr); + nullptr, &quality, nullptr); if (soxr == nullptr) { error.Format(soxr_domain, "soxr initialization has failed: %s", e); diff --git a/src/pcm/SoxrResampler.hxx b/src/pcm/SoxrResampler.hxx index 74d32e2b5..efe9bd5cb 100644 --- a/src/pcm/SoxrResampler.hxx +++ b/src/pcm/SoxrResampler.hxx @@ -44,4 +44,7 @@ public: Error &error) override; }; +bool +pcm_resample_soxr_global_init(const char *converter, Error &error); + #endif |