Merge commit 'meins/master'
authorAndre Noll <maan@systemlinux.org>
Sat, 19 Jul 2008 15:24:52 +0000 (17:24 +0200)
committerAndre Noll <maan@systemlinux.org>
Sat, 19 Jul 2008 15:24:52 +0000 (17:24 +0200)
NEWS
amp_filter.c [new file with mode: 0644]
amp_filter.ggo [new file with mode: 0644]
compress.c
configure.ac
error.h
filter.h
write.h
write_common.c

diff --git a/NEWS b/NEWS
index 7404ab1d4b6f7cdf7e8439274e08f9a3445718a2..684485cf0bef753424750e45128dbe866439c093 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,17 +5,18 @@ NEWS
 0.3.3 (to be announced) "axiomatic perspectivity"
 -------------------------------------------------
 
-Internal code cleanups, improved tag handling and the new
-amplification feature.
+Internal code cleanups, bug fixes, improved tag handling and the new
+amplification filter.
 
        - para_server uses the generic scheduling code.
        - overhaul of the virtual streaming system.
        - mp3: id3 version 2 support via libid3tag (optional)
        - ogg: vorbis comment support.
        - mp3 audio format handler cleanups.
+       - new filter: "amp" to amplify the amplitude of the audio stream
        - new status item/database entry: amplification. It is
-         used by the compress filter to pre-amplify the amplitude of the
-         audio stream.
+         used by the amp filter to pre-amplify the audio stream.
+       - fix a close-without-open bug in para_write.
 
 -----------------------------------------
 0.3.2 (2008-04-11) "probabilistic parity"
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 8e2f07c9c4f3342e2984c5b4b8b2a0b047bb038c..c30c998a33eb3354968f6801fe4890aea43e3b19 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 79d930de1c7fdaecfdef3d817bd6875c75748239..63cbdc973f7e17d809351c534cf0b9a562766092 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 bbe72bdc6e7adec5b0c438a66e4c1fa5749620cb..4674ec04de88f335e24cde3732af14f154216cd8 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 550c68d64c783113d7c99aa1e0a37fde564cd188..500a85379bd42b0dabdea4383d875a4f2180b640 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 \
diff --git a/write.h b/write.h
index a73ada5d06039b0d9c175c3266b581dd0a79d689..091f8c77181cbf3f1a014e31db2667b534aa5b0d 100644 (file)
--- a/write.h
+++ b/write.h
@@ -113,6 +113,8 @@ struct writer_node_group {
        unsigned int *samplerate;
        /** the task associated to this group */
        struct task task;
+       /** Whether the group is open, i.e. wng_open() was called. */
+       int open;
 };
 
 /** loop over each writer node in a writer group */
index 70a9a0155ff4e0a9e1f9b5bccf1054f1ea7a5275..3bf5d1199f560e9ce93b7d97a06e278ce495591f 100644 (file)
@@ -90,6 +90,7 @@ int wng_open(struct writer_node_group *g)
        }
        sprintf(g->task.status, "%s", "writer node group");
        register_task(&g->task);
+       g->open = 1;
        return 1;
 err_out:
        PARA_ERROR_LOG("%s\n", para_strerror(-ret));
@@ -112,7 +113,7 @@ void wng_close(struct writer_node_group *g)
 {
        int i;
 
-       if (!g)
+       if (!g || !g->open)
                return;
        PARA_NOTICE_LOG("closing wng with %d writer(s)\n", g->num_writers);
        FOR_EACH_WRITER_NODE(i, g) {