Commit 2b3fd0d4 authored by Max Kellermann's avatar Max Kellermann

pcm_resample: one-time global initialization

Load the samplerate_converter on MPD startup. Fail if the converter name is invalid.
parent 894b9cfd
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "volume.h" #include "volume.h"
#include "log.h" #include "log.h"
#include "permission.h" #include "permission.h"
#include "pcm_resample.h"
#include "replay_gain_config.h" #include "replay_gain_config.h"
#include "decoder_list.h" #include "decoder_list.h"
#include "input_init.h" #include "input_init.h"
...@@ -403,6 +404,13 @@ int mpd_main(int argc, char *argv[]) ...@@ -403,6 +404,13 @@ int mpd_main(int argc, char *argv[])
#ifdef ENABLE_ARCHIVE #ifdef ENABLE_ARCHIVE
archive_plugin_init_all(); archive_plugin_init_all();
#endif #endif
if (!pcm_resample_global_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
return EXIT_FAILURE;
}
decoder_plugin_init_all(); decoder_plugin_init_all();
update_global_init(); update_global_init();
......
...@@ -27,14 +27,35 @@ ...@@ -27,14 +27,35 @@
#include <string.h> #include <string.h>
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
static bool lsr_enabled;
#endif
#ifdef HAVE_LIBSAMPLERATE
static bool static bool
pcm_resample_lsr_enabled(void) pcm_resample_lsr_enabled(void)
{ {
return strcmp(config_get_string(CONF_SAMPLERATE_CONVERTER, ""), return lsr_enabled;
"internal") != 0;
} }
#endif #endif
bool
pcm_resample_global_init(GError **error_r)
{
#ifdef HAVE_LIBSAMPLERATE
const char *converter =
config_get_string(CONF_SAMPLERATE_CONVERTER, "");
lsr_enabled = strcmp(converter, "internal") != 0;
if (lsr_enabled)
return pcm_resample_lsr_global_init(converter, error_r);
else
return true;
#else
(void)error_r;
return true;
#endif
}
void pcm_resample_init(struct pcm_resample_state *state) void pcm_resample_init(struct pcm_resample_state *state)
{ {
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
......
...@@ -54,6 +54,9 @@ struct pcm_resample_state { ...@@ -54,6 +54,9 @@ struct pcm_resample_state {
struct pcm_buffer buffer; struct pcm_buffer buffer;
}; };
bool
pcm_resample_global_init(GError **error_r);
/** /**
* Initializes a pcm_resample_state object. * Initializes a pcm_resample_state object.
*/ */
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
bool
pcm_resample_lsr_global_init(const char *converter, GError **error_r);
void void
pcm_resample_lsr_deinit(struct pcm_resample_state *state); pcm_resample_lsr_deinit(struct pcm_resample_state *state);
......
...@@ -30,57 +30,68 @@ ...@@ -30,57 +30,68 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "pcm" #define G_LOG_DOMAIN "pcm"
static int lsr_converter = SRC_SINC_FASTEST;
static inline GQuark static inline GQuark
libsamplerate_quark(void) libsamplerate_quark(void)
{ {
return g_quark_from_static_string("libsamplerate"); return g_quark_from_static_string("libsamplerate");
} }
void static bool
pcm_resample_lsr_deinit(struct pcm_resample_state *state) lsr_parse_converter(const char *s)
{ {
if (state->state != NULL) assert(s != NULL);
state->state = src_delete(state->state);
pcm_buffer_deinit(&state->in); if (*s == 0)
pcm_buffer_deinit(&state->out); return true;
pcm_buffer_deinit(&state->buffer);
}
static int pcm_resample_get_converter(void) char *endptr;
{ long l = strtol(s, &endptr, 10);
const char *conf = config_get_string(CONF_SAMPLERATE_CONVERTER, NULL); if (*endptr == 0 && src_get_name(l) != NULL) {
long convalgo; lsr_converter = l;
char *test; return true;
const char *test2;
size_t len;
if (!conf) {
convalgo = SRC_SINC_FASTEST;
goto out;
} }
convalgo = strtol(conf, &test, 10); size_t length = strlen(s);
if (*test == '\0' && src_get_name(convalgo)) for (int i = 0;; ++i) {
goto out; const char *name = src_get_name(i);
if (name == NULL)
len = strlen(conf);
for (convalgo = 0 ; ; convalgo++) {
test2 = src_get_name(convalgo);
if (!test2) {
convalgo = SRC_SINC_FASTEST;
break; break;
if (g_ascii_strncasecmp(s, name, length) == 0) {
lsr_converter = i;
return true;
} }
if (g_ascii_strncasecmp(test2, conf, len) == 0)
goto out;
} }
g_warning("unknown samplerate converter \"%s\"", conf); return false;
out: }
g_debug("selecting samplerate converter \"%s\"",
src_get_name(convalgo)); bool
pcm_resample_lsr_global_init(const char *converter, GError **error_r)
{
if (!lsr_parse_converter(converter)) {
g_set_error(error_r, libsamplerate_quark(), 0,
"unknown samplerate converter '%s'", converter);
return false;
}
g_debug("libsamplerate converter '%s'",
src_get_name(lsr_converter));
return convalgo; return true;
}
void
pcm_resample_lsr_deinit(struct pcm_resample_state *state)
{
if (state->state != NULL)
state->state = src_delete(state->state);
pcm_buffer_deinit(&state->in);
pcm_buffer_deinit(&state->out);
pcm_buffer_deinit(&state->buffer);
} }
static bool static bool
...@@ -88,13 +99,9 @@ pcm_resample_set(struct pcm_resample_state *state, ...@@ -88,13 +99,9 @@ pcm_resample_set(struct pcm_resample_state *state,
uint8_t channels, unsigned src_rate, unsigned dest_rate, uint8_t channels, unsigned src_rate, unsigned dest_rate,
GError **error_r) GError **error_r)
{ {
static int convalgo = -1;
int error; int error;
SRC_DATA *data = &state->data; SRC_DATA *data = &state->data;
if (convalgo < 0)
convalgo = pcm_resample_get_converter();
/* (re)set the state/ratio if the in or out format changed */ /* (re)set the state/ratio if the in or out format changed */
if (channels == state->prev.channels && if (channels == state->prev.channels &&
src_rate == state->prev.src_rate && src_rate == state->prev.src_rate &&
...@@ -109,7 +116,7 @@ pcm_resample_set(struct pcm_resample_state *state, ...@@ -109,7 +116,7 @@ pcm_resample_set(struct pcm_resample_state *state,
if (state->state) if (state->state)
state->state = src_delete(state->state); state->state = src_delete(state->state);
state->state = src_new(convalgo, channels, &error); state->state = src_new(lsr_converter, channels, &error);
if (!state->state) { if (!state->state) {
g_set_error(error_r, libsamplerate_quark(), state->error, g_set_error(error_r, libsamplerate_quark(), state->error,
"libsamplerate initialization has failed: %s", "libsamplerate initialization has failed: %s",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment