pcm_resample: one-time global initialization

Load the samplerate_converter on MPD startup.  Fail if the converter
name is invalid.
This commit is contained in:
Max Kellermann 2011-10-08 13:14:29 +02:00
parent 894b9cfdb9
commit 2b3fd0d4d3
5 changed files with 85 additions and 43 deletions

View File

@ -44,6 +44,7 @@
#include "volume.h"
#include "log.h"
#include "permission.h"
#include "pcm_resample.h"
#include "replay_gain_config.h"
#include "decoder_list.h"
#include "input_init.h"
@ -403,6 +404,13 @@ int mpd_main(int argc, char *argv[])
#ifdef ENABLE_ARCHIVE
archive_plugin_init_all();
#endif
if (!pcm_resample_global_init(&error)) {
g_warning("%s", error->message);
g_error_free(error);
return EXIT_FAILURE;
}
decoder_plugin_init_all();
update_global_init();

View File

@ -26,15 +26,36 @@
#include <string.h>
#ifdef HAVE_LIBSAMPLERATE
static bool lsr_enabled;
#endif
#ifdef HAVE_LIBSAMPLERATE
static bool
pcm_resample_lsr_enabled(void)
{
return strcmp(config_get_string(CONF_SAMPLERATE_CONVERTER, ""),
"internal") != 0;
return lsr_enabled;
}
#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)
{
memset(state, 0, sizeof(*state));

View File

@ -54,6 +54,9 @@ struct pcm_resample_state {
struct pcm_buffer buffer;
};
bool
pcm_resample_global_init(GError **error_r);
/**
* Initializes a pcm_resample_state object.
*/

View File

@ -32,6 +32,9 @@
#ifdef HAVE_LIBSAMPLERATE
bool
pcm_resample_lsr_global_init(const char *converter, GError **error_r);
void
pcm_resample_lsr_deinit(struct pcm_resample_state *state);

View File

@ -30,12 +30,59 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "pcm"
static int lsr_converter = SRC_SINC_FASTEST;
static inline GQuark
libsamplerate_quark(void)
{
return g_quark_from_static_string("libsamplerate");
}
static bool
lsr_parse_converter(const char *s)
{
assert(s != NULL);
if (*s == 0)
return true;
char *endptr;
long l = strtol(s, &endptr, 10);
if (*endptr == 0 && src_get_name(l) != NULL) {
lsr_converter = l;
return true;
}
size_t length = strlen(s);
for (int i = 0;; ++i) {
const char *name = src_get_name(i);
if (name == NULL)
break;
if (g_ascii_strncasecmp(s, name, length) == 0) {
lsr_converter = i;
return true;
}
}
return false;
}
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 true;
}
void
pcm_resample_lsr_deinit(struct pcm_resample_state *state)
{
@ -47,54 +94,14 @@ pcm_resample_lsr_deinit(struct pcm_resample_state *state)
pcm_buffer_deinit(&state->buffer);
}
static int pcm_resample_get_converter(void)
{
const char *conf = config_get_string(CONF_SAMPLERATE_CONVERTER, NULL);
long convalgo;
char *test;
const char *test2;
size_t len;
if (!conf) {
convalgo = SRC_SINC_FASTEST;
goto out;
}
convalgo = strtol(conf, &test, 10);
if (*test == '\0' && src_get_name(convalgo))
goto out;
len = strlen(conf);
for (convalgo = 0 ; ; convalgo++) {
test2 = src_get_name(convalgo);
if (!test2) {
convalgo = SRC_SINC_FASTEST;
break;
}
if (g_ascii_strncasecmp(test2, conf, len) == 0)
goto out;
}
g_warning("unknown samplerate converter \"%s\"", conf);
out:
g_debug("selecting samplerate converter \"%s\"",
src_get_name(convalgo));
return convalgo;
}
static bool
pcm_resample_set(struct pcm_resample_state *state,
uint8_t channels, unsigned src_rate, unsigned dest_rate,
GError **error_r)
{
static int convalgo = -1;
int error;
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 */
if (channels == state->prev.channels &&
src_rate == state->prev.src_rate &&
@ -109,7 +116,7 @@ pcm_resample_set(struct pcm_resample_state *state,
if (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) {
g_set_error(error_r, libsamplerate_quark(), state->error,
"libsamplerate initialization has failed: %s",