Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gst-plugins-good.git] / gst / audiofx / audioinvert.c
index 188793f..dc61b26 100644 (file)
 
 /**
  * SECTION:element-audioinvert
- * @short_description: Swaps upper and lower half of audio samples
  *
- * <refsect2>
  * Swaps upper and lower half of audio samples. Mixing an inverted sample on top of
  * the original with a slight delay can produce effects that sound like resonance.
  * Creating a stereo sample from a mono source, with one channel inverted produces wide-stereo sounds.
+ *
+ * <refsect2>
  * <title>Example launch line</title>
- * <para>
- * <programlisting>
+ * |[
  * gst-launch audiotestsrc wave=saw ! audioinvert invert=0.4 ! alsasink
  * gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioinvert invert=0.4 ! alsasink
  * gst-launch audiotestsrc wave=saw ! audioconvert ! audioinvert invert=0.4 ! audioconvert ! alsasink
- * </programlisting>
- * </para>
+ * ]|
  * </refsect2>
  */
 
 #include <gst/base/gstbasetransform.h>
 #include <gst/audio/audio.h>
 #include <gst/audio/gstaudiofilter.h>
-#include <gst/controller/gstcontroller.h>
 
 #include "audioinvert.h"
 
 #define GST_CAT_DEFAULT gst_audio_invert_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
-static const GstElementDetails element_details =
-GST_ELEMENT_DETAILS ("Audio inversion",
-    "Filter/Effect/Audio",
-    "Swaps upper and lower half of audio samples",
-    "Sebastian Dröge <slomo@circular-chaos.org>");
-
 /* Filter signals and args */
 enum
 {
@@ -73,24 +64,12 @@ enum
 };
 
 #define ALLOWED_CAPS \
-    "audio/x-raw-int,"                                                \
-    " depth=(int)16,"                                                 \
-    " width=(int)16,"                                                 \
-    " endianness=(int)BYTE_ORDER,"                                    \
-    " signed=(bool)TRUE,"                                             \
-    " rate=(int)[1,MAX],"                                             \
-    " channels=(int)[1,MAX]; "                                        \
-    "audio/x-raw-float,"                                              \
-    " width=(int)32,"                                                 \
-    " endianness=(int)BYTE_ORDER,"                                    \
-    " rate=(int)[1,MAX],"                                             \
-    " channels=(int)[1,MAX]"
-
-#define DEBUG_INIT(bla) \
-  GST_DEBUG_CATEGORY_INIT (gst_audio_invert_debug, "audioinvert", 0, "audioinvert element");
-
-GST_BOILERPLATE_FULL (GstAudioInvert, gst_audio_invert, GstAudioFilter,
-    GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
+    "audio/x-raw,"                                                     \
+    " format=(string) {"GST_AUDIO_NE(S16)","GST_AUDIO_NE(F32)"},"  \
+    " rate=(int)[1,MAX],"                                              \
+    " channels=(int)[1,MAX] "
+
+G_DEFINE_TYPE (GstAudioInvert, gst_audio_invert, GST_TYPE_AUDIO_FILTER);
 
 static void gst_audio_invert_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -98,7 +77,7 @@ static void gst_audio_invert_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static gboolean gst_audio_invert_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * format);
+    const GstAudioInfo * info);
 static GstFlowReturn gst_audio_invert_transform_ip (GstBaseTransform * base,
     GstBuffer * buf);
 
@@ -110,32 +89,36 @@ static void gst_audio_invert_transform_float (GstAudioInvert * filter,
 /* GObject vmethod implementations */
 
 static void
-gst_audio_invert_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstCaps *caps;
-
-  gst_element_class_set_details (element_class, &element_details);
-
-  caps = gst_caps_from_string (ALLOWED_CAPS);
-  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
-      caps);
-  gst_caps_unref (caps);
-}
-
-static void
 gst_audio_invert_class_init (GstAudioInvertClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstCaps *caps;
+
+  GST_DEBUG_CATEGORY_INIT (gst_audio_invert_debug, "audioinvert", 0,
+      "audioinvert element");
 
   gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
   gobject_class->set_property = gst_audio_invert_set_property;
   gobject_class->get_property = gst_audio_invert_get_property;
 
   g_object_class_install_property (gobject_class, PROP_DEGREE,
       g_param_spec_float ("degree", "Degree",
           "Degree of inversion", 0.0, 1.0,
-          0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+          0.0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  gst_element_class_set_details_simple (gstelement_class, "Audio inversion",
+      "Filter/Effect/Audio",
+      "Swaps upper and lower half of audio samples",
+      "Sebastian Dröge <slomo@circular-chaos.org>");
+
+  caps = gst_caps_from_string (ALLOWED_CAPS);
+  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
+      caps);
+  gst_caps_unref (caps);
 
   GST_AUDIO_FILTER_CLASS (klass)->setup =
       GST_DEBUG_FUNCPTR (gst_audio_invert_setup);
@@ -144,7 +127,7 @@ gst_audio_invert_class_init (GstAudioInvertClass * klass)
 }
 
 static void
-gst_audio_invert_init (GstAudioInvert * filter, GstAudioInvertClass * klass)
+gst_audio_invert_init (GstAudioInvert * filter)
 {
   filter->degree = 0.0;
   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
@@ -188,20 +171,24 @@ gst_audio_invert_get_property (GObject * object, guint prop_id,
 /* GstAudioFilter vmethod implementations */
 
 static gboolean
-gst_audio_invert_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+gst_audio_invert_setup (GstAudioFilter * base, const GstAudioInfo * info)
 {
   GstAudioInvert *filter = GST_AUDIO_INVERT (base);
   gboolean ret = TRUE;
 
-  if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
-    filter->process = (GstAudioInvertProcessFunc)
-        gst_audio_invert_transform_float;
-  else if (format->type == GST_BUFTYPE_LINEAR && format->width == 16)
-    filter->process = (GstAudioInvertProcessFunc)
-        gst_audio_invert_transform_int;
-  else
-    ret = FALSE;
-
+  switch (GST_AUDIO_INFO_FORMAT (info)) {
+    case GST_AUDIO_FORMAT_S16:
+      filter->process = (GstAudioInvertProcessFunc)
+          gst_audio_invert_transform_int;
+      break;
+    case GST_AUDIO_FORMAT_F32:
+      filter->process = (GstAudioInvertProcessFunc)
+          gst_audio_invert_transform_float;
+      break;
+    default:
+      ret = FALSE;
+      break;
+  }
   return ret;
 }
 
@@ -238,17 +225,31 @@ static GstFlowReturn
 gst_audio_invert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
 {
   GstAudioInvert *filter = GST_AUDIO_INVERT (base);
-  guint num_samples =
-      GST_BUFFER_SIZE (buf) / (GST_AUDIO_FILTER (filter)->format.width / 8);
+  guint num_samples;
+  GstClockTime timestamp, stream_time;
+  guint8 *data;
+  gsize size;
 
-  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf)))
-    gst_object_sync_values (G_OBJECT (filter), GST_BUFFER_TIMESTAMP (buf));
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+  stream_time =
+      gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
+
+  GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (timestamp));
+
+  if (GST_CLOCK_TIME_IS_VALID (stream_time))
+    gst_object_sync_values (GST_OBJECT (filter), stream_time);
 
   if (gst_base_transform_is_passthrough (base) ||
       G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
     return GST_FLOW_OK;
 
-  filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READWRITE);
+  num_samples = size / GST_AUDIO_FILTER_BPS (filter);
+
+  filter->process (filter, data, num_samples);
+
+  gst_buffer_unmap (buf, data, size);
 
   return GST_FLOW_OK;
 }