summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2005-07-16 16:36:59 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2005-07-16 16:36:59 +0000
commit42e0f1003ad4685d441923f589a2c6518caa8367 (patch)
tree8be02288407eea49643d50f39d23ac6af12ab8d6
parent923f954cb85c28f4b3443f6aa273ac87d59c9ccf (diff)
downloadxine-lib-42e0f1003ad4685d441923f589a2c6518caa8367.tar.gz
xine-lib-42e0f1003ad4685d441923f589a2c6518caa8367.tar.bz2
Reinhard Nissl's plugin to upmix mono to stereo
CVS patchset: 7642 CVS date: 2005/07/16 16:36:59
-rw-r--r--src/post/audio/Makefile.am2
-rw-r--r--src/post/audio/audio_filters.c14
-rw-r--r--src/post/audio/audio_filters.h3
-rw-r--r--src/post/audio/upmix_mono.c367
4 files changed, 378 insertions, 8 deletions
diff --git a/src/post/audio/Makefile.am b/src/post/audio/Makefile.am
index b208a71e9..a7dbe64bf 100644
--- a/src/post/audio/Makefile.am
+++ b/src/post/audio/Makefile.am
@@ -7,7 +7,7 @@ libdir = $(XINE_PLUGINDIR)/post
lib_LTLIBRARIES = xineplug_post_audio_filters.la
xineplug_post_audio_filters_la_SOURCES = \
- upmix.c filter.c window.c stretch.c audio_filters.c
+ upmix.c upmix_mono.c filter.c window.c stretch.c audio_filters.c
xineplug_post_audio_filters_la_LIBADD = $(XINE_LIB)
xineplug_post_audio_filters_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ -lm
diff --git a/src/post/audio/audio_filters.c b/src/post/audio/audio_filters.c
index c773dc7a0..06e0afb86 100644
--- a/src/post/audio/audio_filters.c
+++ b/src/post/audio/audio_filters.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_filters.c,v 1.2 2004/07/27 17:59:58 mroi Exp $
+ * $Id: audio_filters.c,v 1.3 2005/07/16 16:36:59 miguelfreitas Exp $
*
* catalog for audio filter plugins
*/
@@ -30,13 +30,15 @@
#include "audio_filters.h"
-post_info_t upmix_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
-post_info_t stretch_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
+post_info_t upmix_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
+post_info_t upmix_mono_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
+post_info_t stretch_special_info = { XINE_POST_TYPE_AUDIO_FILTER };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 9, "upmix", XINE_VERSION_CODE, &upmix_special_info, &upmix_init_plugin },
- { PLUGIN_POST, 9, "stretch", XINE_VERSION_CODE, &stretch_special_info, &stretch_init_plugin },
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+ { PLUGIN_POST, 9, "upmix", XINE_VERSION_CODE, &upmix_special_info, &upmix_init_plugin },
+ { PLUGIN_POST, 9, "upmix_mono", XINE_VERSION_CODE, &upmix_mono_special_info, &upmix_mono_init_plugin },
+ { PLUGIN_POST, 9, "stretch", XINE_VERSION_CODE, &stretch_special_info, &stretch_init_plugin },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/post/audio/audio_filters.h b/src/post/audio/audio_filters.h
index 365c13346..d60fa7e32 100644
--- a/src/post/audio/audio_filters.h
+++ b/src/post/audio/audio_filters.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_filters.h,v 1.1 2004/07/27 17:59:58 mroi Exp $
+ * $Id: audio_filters.h,v 1.2 2005/07/16 16:36:59 miguelfreitas Exp $
*
* catalog for audio filter plugins
*/
@@ -26,4 +26,5 @@
void *upmix_init_plugin(xine_t *xine, void *data);
+void *upmix_mono_init_plugin(xine_t *xine, void *data);
void *stretch_init_plugin(xine_t *xine, void *data);
diff --git a/src/post/audio/upmix_mono.c b/src/post/audio/upmix_mono.c
new file mode 100644
index 000000000..0be676d4e
--- /dev/null
+++ b/src/post/audio/upmix_mono.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Upmix audio filter for xine.
+ * (c) 2004 James Courtier-Dutton (James@superbug.demon.co.uk)
+ * This is an up-mix audio filter post plugin.
+ * It simply converts Mono into Stereo.
+ *
+ * $Id: upmix_mono.c,v 1.1 2005/07/16 16:36:59 miguelfreitas Exp $
+ *
+ */
+
+#include <stdio.h>
+
+#define LOG_MODULE "upmix_mono"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include "xineutils.h"
+#include "post.h"
+
+#include "audio_filters.h"
+
+typedef struct upmix_mono_parameters_s {
+ int channel;
+} upmix_mono_parameters_t;
+
+/*
+ * description of params struct
+ */
+START_PARAM_DESCR( upmix_mono_parameters_t )
+PARAM_ITEM( POST_PARAM_TYPE_INT, channel, NULL, 0, 5, 0,
+ "Select channel to upmix (duplicate) to stereo" )
+END_PARAM_DESCR( param_descr )
+
+
+typedef struct post_plugin_upmix_mono_s post_plugin_upmix_mono_t;
+
+typedef struct post_class_upmix_mono_s post_class_upmix_mono_t;
+
+struct post_class_upmix_mono_s {
+ post_class_t post_class;
+
+ xine_t *xine;
+};
+
+struct post_plugin_upmix_mono_s {
+ post_plugin_t post;
+
+ /* private data */
+ int channels;
+
+ upmix_mono_parameters_t params;
+ xine_post_in_t params_input;
+ int params_changed;
+
+ pthread_mutex_t lock;
+
+};
+
+/**************************************************************************
+ * upmix_mono parameters functions
+ *************************************************************************/
+static int set_parameters (xine_post_t *this_gen, void *param_gen) {
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)this_gen;
+ upmix_mono_parameters_t *param = (upmix_mono_parameters_t *)param_gen;
+
+ pthread_mutex_lock (&this->lock);
+ memcpy( &this->params, param, sizeof(upmix_mono_parameters_t) );
+ this->params_changed = 1;
+ pthread_mutex_unlock (&this->lock);
+
+ return 1;
+}
+static int get_parameters (xine_post_t *this_gen, void *param_gen) {
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)this_gen;
+ upmix_mono_parameters_t *param = (upmix_mono_parameters_t *)param_gen;
+
+ pthread_mutex_lock (&this->lock);
+ memcpy( param, &this->params, sizeof(upmix_mono_parameters_t) );
+ pthread_mutex_unlock (&this->lock);
+
+ return 1;
+}
+
+static xine_post_api_descr_t * get_param_descr (void) {
+ return &param_descr;
+}
+
+static char * get_help (void) {
+ return _("This filter will upmix a mono stream to stereo, by "
+ "duplicating channels. Alternatively, one may use this "
+ "plugin to listen just one channel of a given stream.\n"
+ );
+}
+
+static xine_post_api_t post_api = {
+ set_parameters,
+ get_parameters,
+ get_param_descr,
+ get_help,
+};
+
+
+/**************************************************************************
+ * xine audio post plugin functions
+ *************************************************************************/
+
+static int upmix_mono_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
+ uint32_t bits, uint32_t rate, int mode) {
+
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)port->post;
+ uint32_t capabilities;
+
+ _x_post_rewire(&this->post);
+ _x_post_inc_usage(port);
+
+ port->stream = stream;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
+ this->channels = _x_ao_mode2channels(mode);
+ capabilities = port->original_port->get_capabilities(port->original_port);
+
+ if (this->channels == 1 && (capabilities & AO_CAP_MODE_STEREO)) {
+ xprintf(stream->xine, XINE_VERBOSITY_LOG,
+ _(LOG_MODULE ": upmixing Mono to Stereo.\n"));
+ mode = AO_CAP_MODE_STEREO;
+ } else {
+ if ( this->channels != 1)
+ xprintf(stream->xine, XINE_VERBOSITY_LOG,
+ _(LOG_MODULE ": upmixing a single channel from original %d channels stream.\n"), this->channels);
+ else {
+ xprintf(stream->xine, XINE_VERBOSITY_LOG,
+ _(LOG_MODULE ": audio device not capable of AO_CAP_MODE_STEREO.\n"));
+ this->channels = 0;
+ }
+ }
+
+ return port->original_port->open(port->original_port, stream, bits, rate, mode);
+}
+
+static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen,
+ audio_buffer_t *buf, xine_stream_t *stream) {
+
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)port->post;
+
+ pthread_mutex_lock (&this->lock);
+
+ if (this->channels == 1)
+ {
+ audio_buffer_t *buf0 = port->original_port->get_buffer(port->original_port);
+ audio_buffer_t *buf1 = port->original_port->get_buffer(port->original_port);
+ buf0->num_frames = buf->num_frames / 2;
+ buf1->num_frames = buf->num_frames - (buf->num_frames / 2);
+ buf0->vpts = buf->vpts;
+ buf1->vpts = 0;
+ buf0->frame_header_count = buf->frame_header_count;
+ buf1->frame_header_count = buf->frame_header_count;
+ buf0->first_access_unit = buf->first_access_unit;
+ buf1->first_access_unit = buf->first_access_unit;
+ /* FIXME: The audio buffer should contain this info.
+ * We should not have to get it from the open call.
+ */
+ buf0->format.bits = buf->format.bits;
+ buf1->format.bits = buf->format.bits;
+ buf0->format.rate = buf->format.rate;
+ buf1->format.rate = buf->format.rate;
+ buf0->format.mode = AO_CAP_MODE_STEREO;
+ buf1->format.mode = AO_CAP_MODE_STEREO;
+ _x_extra_info_merge(buf0->extra_info, buf->extra_info);
+ _x_extra_info_merge(buf1->extra_info, buf->extra_info);
+
+ {
+ int step = buf->format.bits / 8;
+ uint8_t *src = (uint8_t *)buf->mem;
+ uint8_t *dst0 = (uint8_t *)buf0->mem;
+ uint8_t *dst1 = (uint8_t *)buf1->mem;
+
+ int i, k;
+ for (i = 0; i < buf->num_frames / 2; i++)
+ {
+ for (k = 0; k < step; k++)
+ *dst0++ = *src++;
+
+ src -= step;
+
+ for (k = 0; k < step; k++)
+ *dst0++ = *src++;
+ }
+
+ for (i = buf->num_frames / 2; i < buf->num_frames; i++)
+ {
+ for (k = 0; k < step; k++)
+ *dst1++ = *src++;
+
+ src -= step;
+
+ for (k = 0; k < step; k++)
+ *dst1++ = *src++;
+ }
+ }
+
+ /* pass data to original port */
+ port->original_port->put_buffer(port->original_port, buf0, stream);
+ port->original_port->put_buffer(port->original_port, buf1, stream);
+
+ /* free data from origial buffer */
+ buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */
+ }
+ else if (this->channels)
+ {
+ audio_buffer_t *buf0 = port->original_port->get_buffer(port->original_port);
+ buf0->num_frames = buf->num_frames;
+ buf0->vpts = buf->vpts;
+ buf0->frame_header_count = buf->frame_header_count;
+ buf0->first_access_unit = buf->first_access_unit;
+ /* FIXME: The audio buffer should contain this info.
+ * We should not have to get it from the open call.
+ */
+ buf0->format.bits = buf->format.bits;
+ buf0->format.rate = buf->format.rate;
+ buf0->format.mode = AO_CAP_MODE_STEREO;
+ _x_extra_info_merge(buf0->extra_info, buf->extra_info);
+
+ {
+ int step = buf->format.bits / 8;
+ uint8_t *src = (uint8_t *)buf->mem;
+ uint8_t *dst0 = (uint8_t *)buf0->mem;
+ int cur_channel = this->params.channel;
+ int i, j, k;
+
+ if( cur_channel >= this->channels )
+ cur_channel = this->channels-1;
+
+ src += cur_channel * step;
+
+ for (i = 0; i < buf->num_frames; i++)
+ {
+ for (j = 0; j < this->channels; j++ )
+ {
+ for (k = 0; k < step; k++)
+ *dst0++ = *(src+k);
+ }
+ src += this->channels * step;
+ }
+ }
+
+ /* pass data to original port */
+ port->original_port->put_buffer(port->original_port, buf0, stream);
+
+ /* free data from origial buffer */
+ buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */
+ }
+
+ pthread_mutex_unlock (&this->lock);
+
+ port->original_port->put_buffer(port->original_port, buf, stream);
+
+ return;
+}
+
+static void upmix_mono_dispose(post_plugin_t *this_gen)
+{
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)this_gen;
+
+ if (_x_post_dispose(this_gen))
+ free(this);
+}
+
+/* plugin class functions */
+static post_plugin_t *upmix_mono_open_plugin(post_class_t *class_gen, int inputs,
+ xine_audio_port_t **audio_target,
+ xine_video_port_t **video_target)
+{
+ post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)xine_xmalloc(sizeof(post_plugin_upmix_mono_t));
+ post_in_t *input;
+ post_out_t *output;
+ xine_post_in_t *input_api;
+ post_audio_port_t *port;
+ upmix_mono_parameters_t init_params;
+
+ if (!this || !audio_target || !audio_target[0]) {
+ free(this);
+ return NULL;
+ }
+
+ _x_post_init(&this->post, 1, 0);
+
+ init_params.channel = 0;
+
+ pthread_mutex_init (&this->lock, NULL);
+
+ set_parameters ((xine_post_t *)&this->post, &init_params);
+
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = upmix_mono_port_open;
+ port->new_port.put_buffer = upmix_mono_port_put_buffer;
+
+ input_api = &this->params_input;
+ input_api->name = "parameters";
+ input_api->type = XINE_POST_DATA_PARAMETERS;
+ input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+
+ input->xine_in.name = "audio";
+ output->xine_out.name = "upmixed audio";
+ this->post.xine_post.audio_input[0] = &port->new_port;
+ this->post.dispose = upmix_mono_dispose;
+
+ return &this->post;
+}
+
+static char *upmix_mono_get_identifier(post_class_t *class_gen)
+{
+ return "upmix_mono";
+}
+
+static char *upmix_mono_get_description(post_class_t *class_gen)
+{
+ return "converts Mono into Stereo";
+}
+
+static void upmix_mono_class_dispose(post_class_t *class_gen)
+{
+ free(class_gen);
+}
+
+/* plugin class initialization function */
+void *upmix_mono_init_plugin(xine_t *xine, void *data)
+{
+ post_class_upmix_mono_t *class = (post_class_upmix_mono_t *)malloc(sizeof(post_class_upmix_mono_t));
+
+ if (!class)
+ return NULL;
+
+ class->post_class.open_plugin = upmix_mono_open_plugin;
+ class->post_class.get_identifier = upmix_mono_get_identifier;
+ class->post_class.get_description = upmix_mono_get_description;
+ class->post_class.dispose = upmix_mono_class_dispose;
+
+ class->xine = xine;
+
+ return class;
+}
+