rework score formula
[paraslash.git] / resample_filter.c
index ef8a701..bbdda51 100644 (file)
@@ -1,27 +1,27 @@
-/*
- * Copyright (C) 2012-2014 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2012 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
 
 /** \file resample_filter.c A sample rate converter based on libsamplerate. */
 
 #include <regex.h>
 #include <samplerate.h>
+#include <lopsub.h>
 
-#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,13 +52,12 @@ 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);
 }
@@ -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);
@@ -207,7 +192,6 @@ static int resample_post_select(__a_unused struct sched *s, void *context)
        int ret;
        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, void *context)
        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
+};