gststereo.c 6.37 KB
Newer Older
1
/* GStreamer
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 *
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

20 21 22 23 24
/* 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 ;-)
 */

25 26 27
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
28
#include "gststereo.h"
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
29

30
/* elementfactory information */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
31 32 33 34
static GstElementDetails stereo_details = GST_ELEMENT_DETAILS ("Stereo effect",
    "Filter/Effect/Audio",
    "Muck with the stereo signal to enhance its 'stereo-ness'",
    "Erik Walthinsen <omega@cse.ogi.edu>");
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
35 36 37


/* Stereo signals and args */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
38 39
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
40 41 42 43
  /* FILL ME */
  LAST_SIGNAL
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
44 45
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
46 47 48 49 50 51
  ARG_0,
  ARG_ACTIVE,
  ARG_STEREO
};


Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
52 53 54
static void gst_stereo_base_init (gpointer g_class);
static void gst_stereo_class_init (GstStereoClass * klass);
static void gst_stereo_init (GstStereo * stereo);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
55

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
56 57 58 59
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);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
60

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
61
static void gst_stereo_chain (GstPad * pad, GstData * _data);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
62 63

static GstElementClass *parent_class = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64

65
/*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
66 67

GType
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
68 69
gst_stereo_get_type (void)
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
70 71 72 73
  static GType stereo_type = 0;

  if (!stereo_type) {
    static const GTypeInfo stereo_info = {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
74
      sizeof (GstStereoClass),
75
      gst_stereo_base_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
76
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
77
      (GClassInitFunc) gst_stereo_class_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
78 79
      NULL,
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
80
      sizeof (GstStereo),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
81
      0,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
82
      (GInstanceInitFunc) gst_stereo_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
83
    };
84

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
85
    stereo_type =
86
        g_type_register_static (GST_TYPE_ELEMENT, "GstStereo", &stereo_info, 0);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
87 88 89 90
  }
  return stereo_type;
}

91 92 93 94
static void
gst_stereo_base_init (gpointer g_class)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
95

96 97
  gst_element_class_set_details (element_class, &stereo_details);
}
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
98
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
99
gst_stereo_class_init (GstStereoClass * klass)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
100 101 102 103
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
104 105
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
106

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
107
  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
108

109 110
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACTIVE, g_param_spec_int ("active", "active", "active", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));      /* CHECKME */
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STEREO, g_param_spec_float ("stereo", "stereo", "stereo", 0.0, 1.0, 0.0, G_PARAM_READWRITE));    /* CHECKME */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
111 112 113 114 115 116

  gobject_class->set_property = gst_stereo_set_property;
  gobject_class->get_property = gst_stereo_get_property;
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
117
gst_stereo_init (GstStereo * stereo)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
118
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
119 120 121 122 123
  stereo->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
  gst_element_add_pad (GST_ELEMENT (stereo), stereo->sinkpad);
  gst_pad_set_chain_function (stereo->sinkpad, gst_stereo_chain);
  stereo->srcpad = gst_pad_new ("src", GST_PAD_SRC);
  gst_element_add_pad (GST_ELEMENT (stereo), stereo->srcpad);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
124 125 126 127 128 129

  stereo->active = FALSE;
  stereo->stereo = 2.5;
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
130
gst_stereo_chain (GstPad * pad, GstData * _data)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
131
{
132
  GstBuffer *buf = GST_BUFFER (_data);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
133 134 135 136
  GstStereo *stereo;
  gint16 *data;
  gint samples;
  gint i;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
137
  gdouble avg, ldiff, rdiff, tmp, mul;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
138

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
139 140 141
  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
142

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
143 144 145
  stereo = GST_STEREO (GST_OBJECT_PARENT (pad));
  g_return_if_fail (stereo != NULL);
  g_return_if_fail (GST_IS_STEREO (stereo));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
146

147 148 149
/*  FIXME */
/*  if (buf->meta) */
/*    memcpy(&stereo->meta,buf->meta,sizeof(stereo->meta)); */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
150 151 152

  if (stereo->active) {

153
    /*if (stereo->meta.channels == 2 && stereo->meta.format == AFMT_S16_LE) { */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
154 155 156 157 158 159 160 161 162 163
    data = (gint16 *) GST_BUFFER_DATA (buf);
    samples = GST_BUFFER_SIZE (buf) / 2;
    mul = stereo->stereo;
    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)
164
        tmp = -32768;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
165
      if (tmp > 32767)
166
        tmp = 32767;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
167 168 169 170
      data[i] = tmp;

      tmp = avg + rdiff * mul;
      if (tmp < -32768)
171
        tmp = -32768;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
172
      if (tmp > 32767)
173
        tmp = 32767;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
174 175
      data[i + 1] = tmp;
    }
176
    /*} */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
177 178
  }

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
179
  gst_pad_push (stereo->srcpad, GST_DATA (buf));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
180 181 182
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
183 184
gst_stereo_set_property (GObject * object, guint prop_id, const GValue * value,
    GParamSpec * pspec)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
185 186 187 188
{
  GstStereo *stereo;

  /* it's not null if we got it, but it might not be ours */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
189 190
  g_return_if_fail (GST_IS_STEREO (object));
  stereo = GST_STEREO (object);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204

  switch (prop_id) {
    case ARG_ACTIVE:
      stereo->active = g_value_get_int (value);
      break;
    case ARG_STEREO:
      stereo->stereo = g_value_get_float (value) * 10.0;
      break;
    default:
      break;
  }
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
205 206
gst_stereo_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
207 208 209 210
{
  GstStereo *stereo;

  /* it's not null if we got it, but it might not be ours */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
211 212
  g_return_if_fail (GST_IS_STEREO (object));
  stereo = GST_STEREO (object);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

  switch (prop_id) {
    case ARG_ACTIVE:
      g_value_set_int (value, stereo->active);
      break;
    case ARG_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
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
228
plugin_init (GstPlugin * plugin)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
229
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
230 231
  return gst_element_register (plugin, "stereo", GST_RANK_NONE,
      GST_TYPE_STEREO);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
232 233
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
234 235 236 237 238
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    "stereo",
    "Muck with the stereo signal, enhance it's 'stereo-ness'",
    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)