From 0d3b26b3aaee6646ce5e825feca43299365797ec Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 21 Jan 2015 20:42:41 +0100 Subject: Config: add section "resampler" --- src/pcm/ConfiguredResampler.cxx | 123 +++++++++++++++++++++++++++++++------ src/pcm/LibsamplerateResampler.cxx | 4 +- src/pcm/LibsamplerateResampler.hxx | 4 +- src/pcm/SoxrResampler.cxx | 22 +++---- src/pcm/SoxrResampler.hxx | 3 +- 5 files changed, 123 insertions(+), 33 deletions(-) (limited to 'src/pcm') diff --git a/src/pcm/ConfiguredResampler.cxx b/src/pcm/ConfiguredResampler.cxx index bf6ea58ee..30cb801c7 100644 --- a/src/pcm/ConfiguredResampler.cxx +++ b/src/pcm/ConfiguredResampler.cxx @@ -23,6 +23,8 @@ #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" #include "config/ConfigError.hxx" +#include "config/Block.hxx" +#include "config/Param.hxx" #include "util/Error.hxx" #ifdef ENABLE_LIBSAMPLERATE @@ -49,34 +51,119 @@ enum class SelectedResampler { static SelectedResampler selected_resampler = SelectedResampler::FALLBACK; +static const ConfigBlock * +MakeResamplerDefaultConfig(ConfigBlock &block) +{ + assert(block.IsEmpty()); + +#ifdef ENABLE_LIBSAMPLERATE + block.AddBlockParam("plugin", "libsamplerate"); +#elif defined(ENABLE_SOXR) + block.AddBlockParam("plugin", "soxr"); +#else + block.AddBlockParam("plugin", "internal"); +#endif + return █ +} + +/** + * Convert the old "samplerate_converter" setting to a new-style + * "resampler" block. + */ +static const ConfigBlock * +MigrateResamplerConfig(const config_param ¶m, ConfigBlock &block) +{ + assert(block.IsEmpty()); + + block.line = param.line; + + const char *converter = param.value.c_str(); + if (*converter == 0 || strcmp(converter, "internal") == 0) { + block.AddBlockParam("plugin", "internal"); + return █ + } + +#ifdef ENABLE_SOXR + if (strcmp(converter, "soxr") == 0) { + block.AddBlockParam("plugin", "soxr"); + return █ + } + + if (memcmp(converter, "soxr ", 5) == 0) { + block.AddBlockParam("plugin", "soxr"); + block.AddBlockParam("quality", converter + 5); + return █ + } +#endif + + block.AddBlockParam("plugin", "libsamplerate"); + block.AddBlockParam("type", converter); + return █ +} + +static const ConfigBlock * +MigrateResamplerConfig(const config_param *param, ConfigBlock &buffer) +{ + assert(buffer.IsEmpty()); + + return param == nullptr + ? MakeResamplerDefaultConfig(buffer) + : MigrateResamplerConfig(*param, buffer); +} + +static const ConfigBlock * +GetResamplerConfig(ConfigBlock &buffer, Error &error) +{ + const auto *old_param = + config_get_param(ConfigOption::SAMPLERATE_CONVERTER); + const auto *block = config_get_block(ConfigBlockOption::RESAMPLER); + if (block == nullptr) + return MigrateResamplerConfig(old_param, buffer); + + if (old_param != nullptr) { + error.Format(config_domain, + "Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)", + block->line, old_param->line); + return nullptr; + } + + return block; +} + bool pcm_resampler_global_init(Error &error) { - const char *converter = - config_get_string(ConfigOption::SAMPLERATE_CONVERTER, ""); + ConfigBlock buffer; + const auto *block = GetResamplerConfig(buffer, error); + if (block == nullptr) + return false; + + const char *plugin_name = block->GetBlockValue("plugin"); + if (plugin_name == nullptr) { + error.Format(config_domain, + "'plugin' missing in line %d", block->line); + return false; + } - if (strcmp(converter, "internal") == 0) + if (strcmp(plugin_name, "internal") == 0) { + selected_resampler = SelectedResampler::FALLBACK; return true; - #ifdef ENABLE_SOXR - if (memcmp(converter, "soxr", 4) == 0) { + } else if (strcmp(plugin_name, "soxr") == 0) { selected_resampler = SelectedResampler::SOXR; - return pcm_resample_soxr_global_init(converter, error); - } + return pcm_resample_soxr_global_init(*block, error); #endif - #ifdef ENABLE_LIBSAMPLERATE - selected_resampler = SelectedResampler::LIBSAMPLERATE; - return pcm_resample_lsr_global_init(converter, error); + } else if (strcmp(plugin_name, "libsamplerate") == 0) { + selected_resampler = SelectedResampler::LIBSAMPLERATE; + return pcm_resample_lsr_global_init(*block, error); #endif - - if (*converter == 0) - return true; - - error.Format(config_domain, - "The samplerate_converter '%s' is not available", - converter); - return false; + } else { + error.Format(config_domain, + "No such resampler plugin: %s", + plugin_name); + return false; + } } PcmResampler * diff --git a/src/pcm/LibsamplerateResampler.cxx b/src/pcm/LibsamplerateResampler.cxx index 73ed33644..cc6f3d43f 100644 --- a/src/pcm/LibsamplerateResampler.cxx +++ b/src/pcm/LibsamplerateResampler.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "LibsamplerateResampler.hxx" +#include "config/Block.hxx" #include "util/ASCII.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -63,8 +64,9 @@ lsr_parse_converter(const char *s) } bool -pcm_resample_lsr_global_init(const char *converter, Error &error) +pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error) { + const char *converter = block.GetBlockValue("type", "2"); if (!lsr_parse_converter(converter)) { error.Format(libsamplerate_domain, "unknown samplerate converter '%s'", converter); diff --git a/src/pcm/LibsamplerateResampler.hxx b/src/pcm/LibsamplerateResampler.hxx index 1ae70ef71..f19dc19eb 100644 --- a/src/pcm/LibsamplerateResampler.hxx +++ b/src/pcm/LibsamplerateResampler.hxx @@ -27,6 +27,8 @@ #include +struct ConfigBlock; + /** * A resampler using libsamplerate. */ @@ -51,6 +53,6 @@ private: }; bool -pcm_resample_lsr_global_init(const char *converter, Error &error); +pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error); #endif diff --git a/src/pcm/SoxrResampler.cxx b/src/pcm/SoxrResampler.cxx index 878c95337..3c271261b 100644 --- a/src/pcm/SoxrResampler.cxx +++ b/src/pcm/SoxrResampler.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "SoxrResampler.hxx" #include "AudioFormat.hxx" +#include "config/Block.hxx" #include "util/ASCII.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -62,18 +63,11 @@ soxr_quality_name(unsigned long recipe) gcc_pure static unsigned long -soxr_parse_converter(const char *converter) +soxr_parse_quality(const char *quality) { - assert(converter != nullptr); - - assert(memcmp(converter, "soxr", 4) == 0); - if (converter[4] == '\0') + if (quality == nullptr) return SOXR_DEFAULT_RECIPE; - if (converter[4] != ' ') - return SOXR_INVALID_RECIPE; - // converter example is "soxr very high", we want the "very high" part - const char *quality = converter + 5; if (strcmp(quality, "very high") == 0) return SOXR_VHQ; else if (strcmp(quality, "high") == 0) @@ -89,12 +83,16 @@ soxr_parse_converter(const char *converter) } bool -pcm_resample_soxr_global_init(const char *converter, Error &error) +pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error) { - unsigned long recipe = soxr_parse_converter(converter); + const char *quality_string = block.GetBlockValue("quality"); + unsigned long recipe = soxr_parse_quality(quality_string); if (recipe == SOXR_INVALID_RECIPE) { + assert(quality_string != nullptr); + error.Format(soxr_domain, - "unknown samplerate converter '%s'", converter); + "unknown quality setting '%s' in line %d", + quality_string, block.line); return false; } diff --git a/src/pcm/SoxrResampler.hxx b/src/pcm/SoxrResampler.hxx index 7756bcea8..6c31ca45a 100644 --- a/src/pcm/SoxrResampler.hxx +++ b/src/pcm/SoxrResampler.hxx @@ -25,6 +25,7 @@ #include "Compiler.h" struct AudioFormat; +struct ConfigBlock; /** * A resampler using soxr. @@ -46,6 +47,6 @@ public: }; bool -pcm_resample_soxr_global_init(const char *converter, Error &error); +pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error); #endif -- cgit v1.2.3