diff --git a/gst/audiofx/gststereo.c b/gst/audiofx/gststereo.c new file mode 100644 index 0000000000..95ca3526aa --- /dev/null +++ b/gst/audiofx/gststereo.c @@ -0,0 +1,214 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* This effect is borrowed from xmms-0.6.1, though I mangled it so badly in + * the process of copying it over that the xmms people probably won't want + * any credit for it ;-) + */ +/** + * SECTION:element-stereo + * @title: stereo + * + * Create a wide stereo effect. + * + * ## Example pipelines + * |[ + * gst-launch-1.0 -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! stereo ! audioconvert ! audioresample ! alsasink + * ]| Play an Ogg/Vorbis file. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gststereo.h" + +#include +#include +#include +#include + +#define ALLOWED_CAPS \ + "audio/x-raw," \ + " format = "GST_AUDIO_NE (S16) "," \ + " rate = (int) [ 1, MAX ]," \ + " channels = (int) 2" + +/* Stereo signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_ACTIVE, + PROP_STEREO +}; + +static void gst_stereo_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_stereo_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_stereo_transform_ip (GstBaseTransform * base, + GstBuffer * outbuf); + +G_DEFINE_TYPE (GstStereo, gst_stereo, GST_TYPE_AUDIO_FILTER); + +static void +gst_stereo_class_init (GstStereoClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass); + GstAudioFilterClass *audiofilter_class = GST_AUDIO_FILTER_CLASS (klass); + GstCaps *caps; + + gst_element_class_set_static_metadata (element_class, "Stereo effect", + "Filter/Effect/Audio", + "Muck with the stereo signal to enhance its 'stereo-ness'", + "Erik Walthinsen "); + + caps = gst_caps_from_string (ALLOWED_CAPS); + gst_audio_filter_class_add_pad_templates (audiofilter_class, caps); + gst_caps_unref (caps); + + gobject_class->set_property = gst_stereo_set_property; + gobject_class->get_property = gst_stereo_get_property; + + g_object_class_install_property (gobject_class, PROP_ACTIVE, + g_param_spec_boolean ("active", "active", "active", + TRUE, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_STEREO, + g_param_spec_float ("stereo", "stereo", "stereo", + 0.0, 1.0, 0.1f, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_stereo_transform_ip); +} + +static void +gst_stereo_init (GstStereo * stereo) +{ + stereo->active = TRUE; + stereo->stereo = 0.1f; +} + +static GstFlowReturn +gst_stereo_transform_ip (GstBaseTransform * base, GstBuffer * outbuf) +{ + GstStereo *stereo = GST_STEREO (base); + gint samples; + gint i; + gdouble avg, ldiff, rdiff, tmp; + gdouble mul = stereo->stereo; + gint16 *data; + GstMapInfo info; + + if (!gst_buffer_map (outbuf, &info, GST_MAP_READWRITE)) + return GST_FLOW_ERROR; + + data = (gint16 *) info.data; + samples = info.size / 2; + + if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (outbuf))) + gst_object_sync_values (GST_OBJECT (stereo), GST_BUFFER_TIMESTAMP (outbuf)); + + if (stereo->active) { + for (i = 0; i < samples / 2; i += 2) { + avg = (data[i] + data[i + 1]) / 2; + ldiff = data[i] - avg; + rdiff = data[i + 1] - avg; + + tmp = avg + ldiff * mul; + if (tmp < -32768) + tmp = -32768; + if (tmp > 32767) + tmp = 32767; + data[i] = tmp; + + tmp = avg + rdiff * mul; + if (tmp < -32768) + tmp = -32768; + if (tmp > 32767) + tmp = 32767; + data[i + 1] = tmp; + } + } + + gst_buffer_unmap (outbuf, &info); + + return GST_FLOW_OK; +} + +static void +gst_stereo_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstStereo *stereo = GST_STEREO (object); + + switch (prop_id) { + case PROP_ACTIVE: + stereo->active = g_value_get_boolean (value); + break; + case PROP_STEREO: + stereo->stereo = g_value_get_float (value) * 10.0; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stereo_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstStereo *stereo = GST_STEREO (object); + + switch (prop_id) { + case PROP_ACTIVE: + g_value_set_boolean (value, stereo->active); + break; + case PROP_STEREO: + g_value_set_float (value, stereo->stereo / 10.0); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "stereo", GST_RANK_NONE, + GST_TYPE_STEREO); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + stereo, + "Muck with the stereo signal, enhance its 'stereo-ness'", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/audiofx/gststereo.h b/gst/audiofx/gststereo.h new file mode 100644 index 0000000000..bd7b6c15b6 --- /dev/null +++ b/gst/audiofx/gststereo.h @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __GST_STEREO_H__ +#define __GST_STEREO_H__ + + +#include +#include + +#define GST_TYPE_STEREO \ + (gst_stereo_get_type()) +#define GST_STEREO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STEREO,GstStereo)) +#define GST_STEREO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STEREO,GstStereoClass)) +#define GST_IS_STEREO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STEREO)) +#define GST_IS_STEREO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STEREO)) + +typedef struct _GstStereo GstStereo; +typedef struct _GstStereoClass GstStereoClass; + +struct _GstStereo { + GstAudioFilter element; + + gboolean active; + gfloat stereo; +}; + +struct _GstStereoClass { + GstAudioFilterClass parent_class; +}; + +GType gst_stereo_get_type(void); + +#endif /* __GST_STEREO_H__ */