Add the new amp filter.
authorAndre Noll <maan@systemlinux.org>
Sat, 12 Jul 2008 10:22:54 +0000 (12:22 +0200)
committerAndre Noll <maan@systemlinux.org>
Sat, 12 Jul 2008 10:22:54 +0000 (12:22 +0200)
Move the amplification code from compress.c to amp_filter.c

amp_filter.c [new file with mode: 0644]
amp_filter.ggo [new file with mode: 0644]
compress.c
configure.ac
error.h
filter.h

diff --git a/amp_filter.c b/amp_filter.c
new file mode 100644 (file)
index 0000000..392fff6
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file amp.c Paraslash's amplify filter. */
+
+#include "para.h"
+#include "amp_filter.cmdline.h"
+#include "list.h"
+#include "sched.h"
+#include "filter.h"
+#include "string.h"
+#include "error.h"
+
+/** The size of the output data buffer. */
+#define AMP_CHUNK_SIZE 40960
+
+extern char *stat_item_values[NUM_STAT_ITEMS];
+
+/** Data specific to the amplify filter. */
+struct private_amp_data {
+       /** Points to the configuration data for this instance of this filter. */
+       struct amp_filter_args_info *conf;
+       /** Amplification factor. */
+       unsigned amp;
+};
+
+static ssize_t amp_convert(char *inbuf, size_t inbuf_len, struct filter_node *fn)
+{
+       size_t i, length = PARA_MIN((inbuf_len / 2) * 2,
+               (fn->bufsize - fn->loaded) / 2 * 2);
+       struct private_amp_data *pad = fn->private_data;
+       int16_t *ip = (int16_t *)inbuf, *op = (int16_t *)(fn->buf + fn->loaded);
+
+       if (!length)
+               return 0;
+       for (i = 0; i < length / 2; i++) {
+               int x = (PARA_ABS(*ip) * (64 + pad->amp)) >> 6;
+               *op++ = *ip++ > 0? PARA_MIN(x, 32767) : PARA_MAX(-x, -32768);
+       }
+       fn->loaded += length;
+       return length;
+}
+
+static void amp_close(struct filter_node *fn)
+{
+       free(fn->private_data);
+       free(fn->buf);
+}
+
+static void *amp_parse_config(int argc, char **argv)
+{
+       struct amp_filter_args_info *conf = para_calloc(sizeof(*conf));
+
+       if (amp_cmdline_parser(argc, argv, conf))
+               goto err;
+       if (conf->amp_arg < 0)
+               goto err;
+       PARA_NOTICE_LOG("amplification: %u (scaling factor: %1.2f)\n", conf->amp_arg,
+               conf->amp_arg / 64.0 + 1.0);
+       return conf;
+err:
+       free(conf);
+       return NULL;
+}
+
+static void amp_open(struct filter_node *fn)
+{
+       struct private_amp_data *pad = para_calloc(sizeof(*pad));
+
+       pad->conf = fn->conf;
+       fn->private_data = pad;
+       if (!pad->conf->amp_given && stat_item_values[SI_AMPLIFICATION]) {
+               int i = SI_AMPLIFICATION;
+               char *s = stat_item_values[i] + strlen(status_item_list[i]) + 1;
+               sscanf(s, "%u", &pad->amp);
+       } else
+               pad->amp = pad->conf->amp_arg;
+       fn->bufsize = AMP_CHUNK_SIZE;
+       fn->buf = para_malloc(fn->bufsize);
+}
+
+/**
+ * The init function of the amplify filter.
+ *
+ * \param f Pointer to the struct to initialize.
+ */
+void amp_init(struct filter *f)
+{
+       f->open = amp_open;
+       f->close = amp_close;
+       f->convert = amp_convert;
+       f->print_help = amp_cmdline_parser_print_help;
+       f->parse_config = amp_parse_config;
+}
diff --git a/amp_filter.ggo b/amp_filter.ggo
new file mode 100644 (file)
index 0000000..1849dc3
--- /dev/null
@@ -0,0 +1,21 @@
+section "The amplify filter"
+
+option "amp" a
+"amplification value"
+int typestr="number"
+default="32"
+optional
+details="
+       The amplification value determines the scaling factor by
+       which the amplitude of the audio stream is multiplied. The
+       formula for the scaling factor is
+
+               factor = 1 + amp / 64
+
+       amp value       scaling factor
+       ~~~~~~~~~       ~~~~~~~~~~~~~~
+       0               1
+       32              1.5
+       64              2
+       128             3
+"
index 8e2f07c..c30c998 100644 (file)
@@ -16,7 +16,6 @@
 #include "sched.h"
 #include "filter.h"
 #include "string.h"
-#include "audiod.h"
 
 /** The size of the output data buffer. */
 #define COMPRESS_CHUNK_SIZE 40960
@@ -35,8 +34,6 @@ struct private_compress_data {
        unsigned num_samples;
        /** Absolute value of the maximal sample in the current block. */
        unsigned peak;
-       /** Amplification factor. */
-       unsigned amp;
 };
 
 static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
@@ -52,9 +49,8 @@ static ssize_t compress(char *inbuf, size_t inbuf_len, struct filter_node *fn)
                return 0;
        for (i = 0; i < length / 2; i++) {
                /* be careful in that heat, my dear */
-               int sample = *ip++, adjusted_sample = (PARA_ABS(sample) * (64 + pcd->amp)) >> 6;
-
-               adjusted_sample = (adjusted_sample * pcd->current_gain) >> gain_shift;
+               int sample = *ip++, adjusted_sample = (PARA_ABS(sample) *
+                       pcd->current_gain) >> gain_shift;
                if (unlikely(adjusted_sample > 32767)) { /* clip */
                        PARA_NOTICE_LOG("clip: sample: %d, adjusted sample: %d\n",
                                sample, adjusted_sample);
@@ -106,13 +102,6 @@ static void open_compress(struct filter_node *fn)
        fn->buf = para_malloc(fn->bufsize);
        pcd->current_gain = 1 << pcd->conf->inertia_arg;
        pcd->max_gain = 1 << (pcd->conf->inertia_arg + pcd->conf->aggressiveness_arg);
-       if (stat_item_values[SI_AMPLIFICATION]) {
-               int i = SI_AMPLIFICATION;
-               char *s = stat_item_values[i] + strlen(status_item_list[i]) + 1;
-               sscanf(s, "%u", &pcd->amp);
-       }
-       PARA_NOTICE_LOG("amplification: %u (scaling factor: %1.2f)\n", pcd->amp,
-               pcd->amp / 64.0 + 1.0);
 }
 
 /**
index 79d930d..63cbdc9 100644 (file)
@@ -79,12 +79,12 @@ AC_CHECK_FUNCS([atexit dup2 memchr memmove memset \
        [AC_MSG_ERROR([function not found, cannot live without it])])
 
 all_errlist_objs="server mp3_afh afh_common vss command net string signal time
-daemon stat crypt http_send close_on_fork ipc acl afh fade
+daemon stat crypt http_send close_on_fork ipc acl afh fade amp_filter
 dccp_send fd user_list chunk_queue afs osl aft mood score attribute blob ringbuffer
 playlist sha1 rbtree sched audiod grab_client filter_chain wav compress
 http_recv dccp_recv recv_common write_common file_write audiod_command
 client_common recv stdout filter stdin audioc write client fsck exec send_common"
-all_executables="server recv filter audioc write client fsck afh"
+all_executables="server recv filter audioc write client fsck afh amp_filter"
 
 recv_cmdline_objs="recv.cmdline http_recv.cmdline dccp_recv.cmdline"
 recv_errlist_objs="http_recv recv_common recv time string net dccp_recv
@@ -94,10 +94,10 @@ recv_ldflags=""
 receivers=" http dccp"
 senders=" http dccp"
 
-filter_cmdline_objs="filter.cmdline compress_filter.cmdline"
-filter_errlist_objs="filter_chain wav compress filter string stdin stdout sched fd"
+filter_cmdline_objs="filter.cmdline compress_filter.cmdline amp_filter.cmdline"
+filter_errlist_objs="filter_chain wav compress filter string stdin stdout sched fd amp_filter"
 filter_ldflags=""
-filters=" compress wav"
+filters=" compress wav amp"
 
 audioc_cmdline_objs="audioc.cmdline"
 audioc_errlist_objs="audioc string net fd"
@@ -105,9 +105,9 @@ audioc_ldflags=""
 
 audiod_cmdline_objs="audiod.cmdline grab_client.cmdline compress_filter.cmdline
        http_recv.cmdline dccp_recv.cmdline file_write.cmdline client.cmdline
-       audiod_command_list"
+       audiod_command_list amp_filter.cmdline"
 audiod_errlist_objs="audiod signal string daemon stat net
-       time grab_client filter_chain wav compress http_recv dccp_recv
+       time grab_client filter_chain wav compress amp_filter http_recv dccp_recv
        recv_common fd sched write_common file_write audiod_command crypt
        client_common"
 audiod_ldflags=""
diff --git a/error.h b/error.h
index bbe72bd..4674ec0 100644 (file)
--- a/error.h
+++ b/error.h
@@ -28,6 +28,8 @@ DEFINE_ERRLIST_OBJECT_ENUM;
 #define SEND_COMMON_ERRORS
 #define STDOUT_ERRORS
 #define IPC_ERRORS
+#define AMP_FILTER_ERRORS
+
 
 
 extern const char **para_errlist[];
index 550c68d..500a853 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -233,6 +233,7 @@ extern struct filter filters[];
 /* filters that are always present */
 DECLARE_EXTERN_FILTER_INIT(wav);
 DECLARE_EXTERN_FILTER_INIT(compress);
+DECLARE_EXTERN_FILTER_INIT(amp);
 
 /* next the optional filters */
 #ifdef HAVE_MAD
@@ -261,6 +262,7 @@ DECLARE_EXTERN_FILTER_INIT(oggdec);
 #define DEFINE_FILTER_ARRAY(filters) struct filter filters[] = { \
        FILTER_INIT(wav) \
        FILTER_INIT(compress) \
+       FILTER_INIT(amp) \
        MP3DEC_FILTER \
        AACDEC_FILTER \
        OGGDEC_FILTER \