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:
parent
894b9cfdb9
commit
2b3fd0d4d3
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue