X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=resample_filter.c;h=bbdda51c525630c6d1411dfa547193f8ccdae9ce;hp=2caa1e21395a7a77909d0284f6e44e3013640857;hb=04c16387cc13317ded03ce478b131d94558f585f;hpb=42ddd68159d7eff0f3e7c225665c97f9abd59425 diff --git a/resample_filter.c b/resample_filter.c index 2caa1e21..bbdda51c 100644 --- a/resample_filter.c +++ b/resample_filter.c @@ -1,27 +1,27 @@ -/* - * Copyright (C) 2012-2014 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2012 Andre Noll , see file COPYING. */ /** \file resample_filter.c A sample rate converter based on libsamplerate. */ #include #include +#include -#include "resample_filter.cmdline.h" +#include "filter_cmd.lsg.h" #include "para.h" #include "error.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" #include "filter.h" #include "string.h" #include "check_wav.h" +#define U32_OPTVAL(_opt, _lpr) (FILTER_CMD_OPT_UINT32_VAL(RESAMPLE, _opt, _lpr)) +#define OPT_GIVEN(_opt, _lpr) (FILTER_CMD_OPT_GIVEN(RESAMPLE, _opt, _lpr)) + +/* effective values, may differ from config arg */ struct resample_context { - int channels; + uint32_t channels; int source_sample_rate; float ratio; SRC_STATE *src_state; @@ -32,10 +32,8 @@ static int resample_execute(struct btr_node *btrn, const char *cmd, char **resul { struct filter_node *fn = btr_context(btrn); struct resample_context *ctx = fn->private_data; - struct resample_filter_args_info *conf = fn->conf; - - return decoder_execute(cmd, conf->dest_sample_rate_arg, ctx->channels, - result); + uint32_t dsr = U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr); + return decoder_execute(cmd, dsr, ctx->channels, result); } static void resample_close(struct filter_node *fn) @@ -54,20 +52,19 @@ static void resample_close(struct filter_node *fn) static void resample_open(struct filter_node *fn) { struct resample_context *ctx = para_calloc(sizeof(*ctx)); - struct resample_filter_args_info *conf = fn->conf; struct btr_node *btrn = fn->btrn; struct wav_params wp; fn->private_data = ctx; fn->min_iqs = 2; - COPY_WAV_PARMS(&wp, conf); + LLS_COPY_WAV_PARMS(&wp, LSG_FILTER_CMD_RESAMPLE, fn->lpr); ctx->cwc = check_wav_init(btr_parent(btrn), btrn, &wp, NULL); btr_log_tree(btr_parent(btr_parent(btrn)), LL_INFO); } -static void resample_pre_select(struct sched *s, struct task *t) +static void resample_pre_select(struct sched *s, void *context) { - struct filter_node *fn = container_of(t, struct filter_node, task); + struct filter_node *fn = context; struct resample_context *ctx = fn->private_data; int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL); @@ -95,18 +92,17 @@ static int resample_set_params(struct filter_node *fn) { int ret; struct resample_context *ctx = fn->private_data; - struct resample_filter_args_info *conf = fn->conf; struct btr_node *btrn = fn->btrn; + struct lls_parse_result *lpr = fn->lpr; - ctx->channels = conf->channels_arg; - if (!conf->channels_given) { + ctx->channels = U32_OPTVAL(CHANNELS, lpr); + if (!OPT_GIVEN(CHANNELS, lpr)) { ret = get_btr_val("channels", btrn); if (ret >= 0) ctx->channels = ret; } - - ctx->source_sample_rate = conf->sample_rate_arg; - if (!conf->sample_rate_given) { + ctx->source_sample_rate = U32_OPTVAL(SAMPLE_RATE, lpr); + if (!OPT_GIVEN(SAMPLE_RATE, lpr)) { ret = get_btr_val("sample_rate", btrn); if (ret >= 0) ctx->source_sample_rate = ret; @@ -114,50 +110,37 @@ static int resample_set_params(struct filter_node *fn) /* reject all sample formats except 16 bit signed, little endian */ ret = get_btr_val("sample_format", btrn); if (ret >= 0 && ret != SF_S16_LE) { - const char *sample_formats[] = {SAMPLE_FORMATS}; + const char * const sample_formats[] = {SAMPLE_FORMATS}; PARA_ERROR_LOG("unsupported sample format: %s\n", sample_formats[ret]); return -ERRNO_TO_PARA_ERROR(EINVAL); } - ctx->ratio = (float)conf->dest_sample_rate_arg / ctx->source_sample_rate; + ctx->ratio = U32_OPTVAL(DEST_SAMPLE_RATE, lpr) + / (float)ctx->source_sample_rate; return 1; } static int resample_init(struct filter_node *fn) { - int ret, converter; + int ret; + const uint32_t trafo[] = { + [RCT_BEST] = SRC_SINC_BEST_QUALITY, + [RCT_MEDIUM] = SRC_SINC_MEDIUM_QUALITY, + [RCT_FASTEST] = SRC_SINC_FASTEST, + [RCT_ZERO_ORDER_HOLD] = SRC_ZERO_ORDER_HOLD, + [RCT_LINEAR] = SRC_LINEAR + }; struct resample_context *ctx = fn->private_data; - struct resample_filter_args_info *conf = fn->conf; - struct btr_node *btrn = fn->btrn; + const struct lls_option *o_c = FILTER_CMD_OPT(RESAMPLE, CONVERTER); + uint32_t converter = U32_OPTVAL(CONVERTER, fn->lpr); - ret = -E_RESAMPLE_EOF; - if (btr_no_parent(btrn)) - return ret; - if (btr_get_input_queue_size(btrn) == 0) - return 0; + PARA_INFO_LOG("converter type: %s\n", + lls_enum_string_val(converter, o_c)); ret = resample_set_params(fn); if (ret < 0) return ret; - switch (conf->converter_arg) { - case converter_arg_best: - converter = SRC_SINC_BEST_QUALITY; - break; - case converter_arg_medium: - converter = SRC_SINC_MEDIUM_QUALITY; - break; - case converter_arg_fastest: - converter = SRC_SINC_FASTEST; - break; - case converter_arg_zero_order_hold: - converter = SRC_ZERO_ORDER_HOLD; - break; - case converter_arg_linear: - converter = SRC_LINEAR; - break; - default: - assert(0); - } - ctx->src_state = src_new(converter, conf->channels_arg, &ret); + ctx->src_state = src_new(trafo[converter], + U32_OPTVAL(CHANNELS, fn->lpr), &ret); if (!ctx->src_state) { PARA_ERROR_LOG("%s\n", src_strerror(ret)); return -E_LIBSAMPLERATE; @@ -172,6 +155,7 @@ static int resample_frames(int16_t *in, size_t num_frames, bool have_more, size_t *result_frames) { int ret, num_samples, out_samples; + float *in_float; int16_t *out; SRC_DATA data; @@ -183,11 +167,12 @@ static int resample_frames(int16_t *in, size_t num_frames, bool have_more, data.output_frames = num_frames * ctx->ratio + 1; out_samples = data.output_frames * ctx->channels; - data.data_in = para_malloc(num_samples * sizeof(float)); - src_short_to_float_array(in, data.data_in, num_samples); + in_float = para_malloc(num_samples * sizeof(float)); + src_short_to_float_array(in, in_float, num_samples); + data.data_in = in_float; data.data_out = para_malloc(out_samples * sizeof(float)); ret = src_process(ctx->src_state, &data); - free(data.data_in); + free(in_float); if (ret != 0) { PARA_ERROR_LOG("%s\n", src_strerror(ret)); free(data.data_out); @@ -202,12 +187,11 @@ static int resample_frames(int16_t *in, size_t num_frames, bool have_more, return data.input_frames_used; } -static int resample_post_select(__a_unused struct sched *s, struct task *t) +static int resample_post_select(__a_unused struct sched *s, void *context) { int ret; - struct filter_node *fn = container_of(t, struct filter_node, task); + struct filter_node *fn = context; struct resample_context *ctx = fn->private_data; - struct resample_filter_args_info *conf = fn->conf; struct btr_node *btrn = fn->btrn; int16_t *in, *out; size_t in_bytes, num_frames; @@ -216,15 +200,15 @@ static int resample_post_select(__a_unused struct sched *s, struct task *t) ret = check_wav_post_select(ctx->cwc); if (ret < 0) goto out; + ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); + if (ret <= 0) + goto out; if (!ctx->src_state) { ret = resample_init(fn); if (ret <= 0) goto out; } - ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); - if (ret <= 0) - goto out; - if (ctx->source_sample_rate == conf->dest_sample_rate_arg) { + if (ctx->source_sample_rate == U32_OPTVAL(DEST_SAMPLE_RATE, fn->lpr)) { /* * No resampling necessary. We do not splice ourselves out * though, since our children might want to ask us through the @@ -257,58 +241,45 @@ out: return ret; } -static int resample_parse_config(int argc, char **argv, void **config) +static void *resample_setup(const struct lls_parse_result *lpr) { - int ret, val, given; - struct resample_filter_args_info *conf = para_calloc(sizeof(*conf)); - - resample_filter_cmdline_parser(argc, argv, conf); + int given; + uint32_t u32; /* sanity checks */ - ret = -ERRNO_TO_PARA_ERROR(EINVAL); - val = conf->channels_arg; - given = conf->channels_given; - if (val < 0 || (val == 0 && given)) - goto err; - val = conf->sample_rate_arg; - given = conf->sample_rate_given; - if (val < 0 || (val == 0 && given)) - goto err; - val = conf->dest_sample_rate_arg; - given = conf->dest_sample_rate_given; - if (val < 0 || (val == 0 && given)) - goto err; - *config = conf; - return 1; -err: - free(conf); - return ret; + u32 = U32_OPTVAL(CHANNELS, lpr); + given = OPT_GIVEN(CHANNELS, lpr); + if (u32 == 0 && given) { + PARA_EMERG_LOG("fatal: zero channels?!\n"); + exit(EXIT_FAILURE); + } + u32 = U32_OPTVAL(SAMPLE_RATE, lpr); + given = OPT_GIVEN(SAMPLE_RATE, lpr); + if (u32 == 0 && given) { + PARA_EMERG_LOG("fatal: input sample rate can not be 0\n"); + exit(EXIT_FAILURE); + } + u32 = U32_OPTVAL(DEST_SAMPLE_RATE, lpr); + given = OPT_GIVEN(DEST_SAMPLE_RATE, lpr); + if (u32 == 0 && given) { + PARA_EMERG_LOG("fatal: destination sample rate can not be 0\n"); + exit(EXIT_FAILURE); + } + return NULL; } -static void resample_free_config(void *conf) +static void resample_teardown(__a_unused const struct lls_parse_result *lpr, + void *conf) { - if (!conf) - return; - resample_filter_cmdline_parser_free(conf); free(conf); } -/** - * The init function of the resample filter. - * - * \param f Structure to initialize. - */ -void resample_filter_init(struct filter *f) -{ - struct resample_filter_args_info dummy; - - resample_filter_cmdline_parser_init(&dummy); - f->close = resample_close; - f->open = resample_open; - f->pre_select = resample_pre_select; - f->post_select = resample_post_select; - f->parse_config = resample_parse_config; - f->free_config = resample_free_config; - f->execute = resample_execute; - f->help = (struct ggo_help)DEFINE_GGO_HELP(resample_filter); -} +const struct filter lsg_filter_cmd_com_resample_user_data = { + .setup = resample_setup, + .open = resample_open, + .pre_select = resample_pre_select, + .post_select = resample_post_select, + .close = resample_close, + .teardown = resample_teardown, + .execute = resample_execute +};