audioamplify: Add noclip method and support for more formats
authorKipp Cannon <kcannon@ligo.caltech.edu>
Fri, 19 Jun 2009 20:20:45 +0000 (22:20 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 19 Jun 2009 20:20:45 +0000 (22:20 +0200)
Fixes bug #585828 and #585831.

gst/audiofx/audioamplify.c
gst/audiofx/audioamplify.h

index da5412a..9e33e55 100644 (file)
@@ -74,6 +74,7 @@ enum
   METHOD_CLIP = 0,
   METHOD_WRAP_NEGATIVE,
   METHOD_WRAP_POSITIVE,
+  METHOD_NOCLIP,
   NUM_METHODS
 };
 
@@ -85,12 +86,13 @@ gst_audio_amplify_clipping_method_get_type (void)
 
   if (gtype == 0) {
     static const GEnumValue values[] = {
-      {METHOD_CLIP, "Normal Clipping (default)", "clip"},
+      {METHOD_CLIP, "Normal clipping (default)", "clip"},
       {METHOD_WRAP_NEGATIVE,
             "Push overdriven values back from the opposite side",
           "wrap-negative"},
       {METHOD_WRAP_POSITIVE, "Push overdriven values back from the same side",
           "wrap-positive"},
+      {METHOD_NOCLIP, "No clipping", "none"},
       {0, NULL, NULL}
     };
 
@@ -100,7 +102,14 @@ gst_audio_amplify_clipping_method_get_type (void)
   return gtype;
 }
 
-#define ALLOWED_CAPS \
+#define ALLOWED_CAPS                                                  \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)8,"                                                  \
+    " width=(int)8,"                                                  \
+    " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
     "audio/x-raw-int,"                                                \
     " depth=(int)16,"                                                 \
     " width=(int)16,"                                                 \
@@ -108,9 +117,16 @@ gst_audio_amplify_clipping_method_get_type (void)
     " signed=(bool)TRUE,"                                             \
     " rate=(int)[1,MAX],"                                             \
     " channels=(int)[1,MAX]; "                                        \
-    "audio/x-raw-float,"                                              \
+    "audio/x-raw-int,"                                                \
+    " depth=(int)32,"                                                 \
     " width=(int)32,"                                                 \
     " endianness=(int)BYTE_ORDER,"                                    \
+    " signed=(bool)TRUE,"                                             \
+    " rate=(int)[1,MAX],"                                             \
+    " channels=(int)[1,MAX]; "                                        \
+    "audio/x-raw-float,"                                              \
+    " width=(int){32,64},"                                            \
+    " endianness=(int)BYTE_ORDER,"                                    \
     " rate=(int)[1,MAX],"                                             \
     " channels=(int)[1,MAX]"
 
@@ -120,6 +136,8 @@ gst_audio_amplify_clipping_method_get_type (void)
 GST_BOILERPLATE_FULL (GstAudioAmplify, gst_audio_amplify, GstAudioFilter,
     GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
 
+static gboolean gst_audio_amplify_set_process_function (GstAudioAmplify *
+    filter, gint clipping, gint format, gint width);
 static void gst_audio_amplify_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_audio_amplify_get_property (GObject * object, guint prop_id,
@@ -130,34 +148,137 @@ static gboolean gst_audio_amplify_setup (GstAudioFilter * filter,
 static GstFlowReturn gst_audio_amplify_transform_ip (GstBaseTransform * base,
     GstBuffer * buf);
 
-static void gst_audio_amplify_transform_int_clip (GstAudioAmplify * filter,
-    gint16 * data, guint num_samples);
-static void gst_audio_amplify_transform_int_wrap_negative (GstAudioAmplify *
-    filter, gint16 * data, guint num_samples);
-static void gst_audio_amplify_transform_int_wrap_positive (GstAudioAmplify *
-    filter, gint16 * data, guint num_samples);
-static void gst_audio_amplify_transform_float_clip (GstAudioAmplify * filter,
-    gfloat * data, guint num_samples);
-static void gst_audio_amplify_transform_float_wrap_negative (GstAudioAmplify *
-    filter, gfloat * data, guint num_samples);
-static void gst_audio_amplify_transform_float_wrap_positive (GstAudioAmplify *
-    filter, gfloat * data, guint num_samples);
-
-/* table of processing functions: [format][clipping_method] */
-static GstAudioAmplifyProcessFunc processing_functions[2][3] = {
-  {
-        (GstAudioAmplifyProcessFunc) gst_audio_amplify_transform_int_clip,
-        (GstAudioAmplifyProcessFunc)
-        gst_audio_amplify_transform_int_wrap_negative,
-        (GstAudioAmplifyProcessFunc)
-      gst_audio_amplify_transform_int_wrap_positive},
-  {
-        (GstAudioAmplifyProcessFunc) gst_audio_amplify_transform_float_clip,
-        (GstAudioAmplifyProcessFunc)
-        gst_audio_amplify_transform_float_wrap_negative,
-        (GstAudioAmplifyProcessFunc)
-      gst_audio_amplify_transform_float_wrap_positive}
-};
+#define MIN_gint8 G_MININT8
+#define MAX_gint8 G_MAXINT8
+#define MIN_gint16 G_MININT16
+#define MAX_gint16 G_MAXINT16
+#define MIN_gint32 G_MININT32
+#define MAX_gint32 G_MAXINT32
+
+#define MAKE_INT_FUNCS(type)                                                  \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    glong val = *d * filter->amplification;                                   \
+    *d++ =  CLAMP (val, MIN_##type, MAX_##type);                              \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    glong val = *d * filter->amplification;                                   \
+    if (val > MAX_##type)                                                     \
+      val = MIN_##type + (val - MIN_##type) % ((glong) MAX_##type -           \
+          MIN_##type);                                                        \
+    else if (val < MIN_##type)                                                \
+      val = MAX_##type - (MAX_##type - val) % ((glong) MAX_##type -           \
+          MIN_##type);                                                        \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    glong val = *d * filter->amplification;                                   \
+    do {                                                                      \
+      if (val > MAX_##type)                                                   \
+        val = MAX_##type - (val - MAX_##type);                                \
+      else if (val < MIN_##type)                                              \
+        val = MIN_##type + (MIN_##type - val);                                \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--)                                                       \
+    *d++ *= filter->amplification;                                            \
+}
+
+#define MAKE_FLOAT_FUNCS(type)                                                \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d* filter->amplification;                                     \
+    *d++ = CLAMP (val, -1.0, +1.0);                                           \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify *         \
+    filter, void * data, guint num_samples)                                   \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d * filter->amplification;                                    \
+    do {                                                                      \
+      if (val > 1.0)                                                          \
+        val = -1.0 + (val - 1.0);                                             \
+      else if (val < -1.0)                                                    \
+        val = 1.0 - (1.0 - val);                                              \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--) {                                                     \
+    type val = *d* filter->amplification;                                     \
+    do {                                                                      \
+      if (val > 1.0)                                                          \
+        val = 1.0 - (val - 1.0);                                              \
+      else if (val < -1.0)                                                    \
+        val = -1.0 + (-1.0 - val);                                            \
+      else                                                                    \
+        break;                                                                \
+    } while (1);                                                              \
+    *d++ = val;                                                               \
+  }                                                                           \
+}                                                                             \
+static void                                                                   \
+gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
+    void * data, guint num_samples)                                           \
+{                                                                             \
+  type *d = data;                                                             \
+                                                                              \
+  while (num_samples--)                                                       \
+    *d++ *= filter->amplification;                                            \
+}
+
+/* *INDENT-OFF* */
+MAKE_INT_FUNCS (gint8)
+MAKE_INT_FUNCS (gint16)
+MAKE_INT_FUNCS (gint32)
+MAKE_FLOAT_FUNCS (gfloat)
+MAKE_FLOAT_FUNCS (gdouble)
 
 /* GObject vmethod implementations */
 
@@ -213,24 +334,90 @@ static void
 gst_audio_amplify_init (GstAudioAmplify * filter, GstAudioAmplifyClass * klass)
 {
   filter->amplification = 1.0;
-  filter->clipping_method = METHOD_CLIP;
-  filter->format_index = 0;
+  gst_audio_amplify_set_process_function (filter, METHOD_CLIP,
+      GST_BUFTYPE_LINEAR, 16);
   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
 }
 
+static GstAudioAmplifyProcessFunc
+gst_audio_amplify_process_function (gint clipping, gint format, gint width)
+{
+  static const struct {
+    gint format;
+    gint width;
+    gint clipping;
+    GstAudioAmplifyProcessFunc func;
+  } *p, process[] = {
+    {GST_BUFTYPE_FLOAT,  32, METHOD_CLIP,
+        gst_audio_amplify_transform_gfloat_clip},
+    {GST_BUFTYPE_FLOAT,  32, METHOD_WRAP_NEGATIVE,
+        gst_audio_amplify_transform_gfloat_wrap_negative},
+    {GST_BUFTYPE_FLOAT,  32, METHOD_WRAP_POSITIVE,
+        gst_audio_amplify_transform_gfloat_wrap_positive},
+    {GST_BUFTYPE_FLOAT,  32, METHOD_NOCLIP,
+        gst_audio_amplify_transform_gfloat_noclip},
+    {GST_BUFTYPE_FLOAT,  64, METHOD_CLIP,
+        gst_audio_amplify_transform_gdouble_clip},
+    {GST_BUFTYPE_FLOAT,  64, METHOD_WRAP_NEGATIVE,
+        gst_audio_amplify_transform_gdouble_wrap_negative},
+    {GST_BUFTYPE_FLOAT,  64, METHOD_WRAP_POSITIVE,
+        gst_audio_amplify_transform_gdouble_wrap_positive},
+    {GST_BUFTYPE_FLOAT,  64, METHOD_NOCLIP,
+        gst_audio_amplify_transform_gdouble_noclip},
+    {GST_BUFTYPE_LINEAR,  8, METHOD_CLIP,
+        gst_audio_amplify_transform_gint8_clip},
+    {GST_BUFTYPE_LINEAR,  8, METHOD_WRAP_NEGATIVE,
+        gst_audio_amplify_transform_gint8_wrap_negative},
+    {GST_BUFTYPE_LINEAR,  8, METHOD_WRAP_POSITIVE,
+        gst_audio_amplify_transform_gint8_wrap_positive},
+    {GST_BUFTYPE_LINEAR,  8, METHOD_NOCLIP,
+        gst_audio_amplify_transform_gint8_noclip},
+    {GST_BUFTYPE_LINEAR, 16, METHOD_CLIP,
+        gst_audio_amplify_transform_gint16_clip},
+    {GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_NEGATIVE,
+        gst_audio_amplify_transform_gint16_wrap_negative},
+    {GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_POSITIVE,
+        gst_audio_amplify_transform_gint16_wrap_positive},
+    {GST_BUFTYPE_LINEAR, 16, METHOD_NOCLIP,
+        gst_audio_amplify_transform_gint16_noclip},
+    {GST_BUFTYPE_LINEAR, 32, METHOD_CLIP,
+        gst_audio_amplify_transform_gint32_clip},
+    {GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_NEGATIVE,
+        gst_audio_amplify_transform_gint32_wrap_negative},
+    {GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_POSITIVE,
+        gst_audio_amplify_transform_gint32_wrap_positive},
+    {GST_BUFTYPE_LINEAR, 32, METHOD_NOCLIP,
+        gst_audio_amplify_transform_gint32_noclip},
+    {0, 0, 0, NULL}
+  };
+
+  for (p = process; p->func; p++)
+    if (p->format == format && p->width == width && p->clipping == clipping)
+      return p->func;
+  return NULL;
+}
+
 static gboolean
-gst_audio_amplify_set_process_function (GstAudioAmplify * filter)
+gst_audio_amplify_set_process_function (GstAudioAmplify * filter, gint
+    clipping_method, gint format, gint width)
 {
-  gint method_index;
+  GstAudioAmplifyProcessFunc process;
 
   /* set processing function */
 
-  method_index = filter->clipping_method;
-  if (method_index >= NUM_METHODS || method_index < 0)
-    method_index = METHOD_CLIP;
+  process = gst_audio_amplify_process_function (clipping_method, format,
+      width);
+  if (!process) {
+    GST_DEBUG ("wrong format");
+    return FALSE;
+  }
+
+  filter->process = process;
+  filter->clipping_method = clipping_method;
+  filter->format = format;
+  filter->width = width;
 
-  filter->process = processing_functions[filter->format_index][method_index];
   return TRUE;
 }
 
@@ -247,8 +434,8 @@ gst_audio_amplify_set_property (GObject * object, guint prop_id,
           filter->amplification == 1.0);
       break;
     case PROP_CLIPPING_METHOD:
-      filter->clipping_method = g_value_get_enum (value);
-      gst_audio_amplify_set_process_function (filter);
+      gst_audio_amplify_set_process_function (filter, g_value_get_enum (value),
+          filter->format, filter->width);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -280,129 +467,9 @@ static gboolean
 gst_audio_amplify_setup (GstAudioFilter * base, GstRingBufferSpec * format)
 {
   GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
-  gboolean ret;
-
-  if (format->type == GST_BUFTYPE_LINEAR && format->width == 16)
-    filter->format_index = 0;
-  else if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
-    filter->format_index = 1;
-  else
-    goto wrong_format;
-
-  ret = gst_audio_amplify_set_process_function (filter);
-  if (!ret)
-    GST_WARNING ("can't process input");
-
-  return ret;
-
-wrong_format:
-  GST_DEBUG ("wrong format");
-  return FALSE;
-}
-
-static void
-gst_audio_amplify_transform_int_clip (GstAudioAmplify * filter,
-    gint16 * data, guint num_samples)
-{
-  gint i;
-  glong val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
-  }
-}
 
-static void
-gst_audio_amplify_transform_int_wrap_negative (GstAudioAmplify * filter,
-    gint16 * data, guint num_samples)
-{
-  gint i;
-  glong val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    if (val > G_MAXINT16)
-      val = ((val - G_MININT16) & 0xffff) + G_MININT16;
-    else if (val < G_MININT16)
-      val = ((val - G_MAXINT16) & 0xffff) + G_MAXINT16;
-    *data++ = val;
-  }
-}
-
-static void
-gst_audio_amplify_transform_int_wrap_positive (GstAudioAmplify * filter,
-    gint16 * data, guint num_samples)
-{
-  gint i;
-  glong val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    while (val > G_MAXINT16 || val < G_MININT16) {
-      if (val > G_MAXINT16)
-        val = G_MAXINT16 - (val - G_MAXINT16);
-      else if (val < G_MININT16)
-        val = G_MININT16 - (val - G_MININT16);
-    }
-    *data++ = val;
-  }
-}
-
-static void
-gst_audio_amplify_transform_float_clip (GstAudioAmplify * filter,
-    gfloat * data, guint num_samples)
-{
-  gint i;
-  gfloat val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    if (val > 1.0)
-      val = 1.0;
-    else if (val < -1.0)
-      val = -1.0;
-
-    *data++ = val;
-  }
-}
-
-static void
-gst_audio_amplify_transform_float_wrap_negative (GstAudioAmplify * filter,
-    gfloat * data, guint num_samples)
-{
-  gint i;
-  gfloat val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    while (val > 1.0 || val < -1.0) {
-      if (val > 1.0)
-        val = -1.0 + (val - 1.0);
-      else if (val < -1.0)
-        val = 1.0 + (val + 1.0);
-    }
-    *data++ = val;
-  }
-}
-
-static void
-gst_audio_amplify_transform_float_wrap_positive (GstAudioAmplify * filter,
-    gfloat * data, guint num_samples)
-{
-  gint i;
-  gfloat val;
-
-  for (i = 0; i < num_samples; i++) {
-    val = (*data) * filter->amplification;
-    while (val > 1.0 || val < -1.0) {
-      if (val > 1.0)
-        val = 1.0 - (val - 1.0);
-      else if (val < -1.0)
-        val = -1.0 - (val + 1.0);
-    }
-    *data++ = val;
-  }
+  return gst_audio_amplify_set_process_function (filter,
+      filter->clipping_method, format->type, format->width);
 }
 
 /* GstBaseTransform vmethod implementations */
index 4924814..b28f38b 100644 (file)
@@ -37,7 +37,7 @@ G_BEGIN_DECLS
 typedef struct _GstAudioAmplify GstAudioAmplify;
 typedef struct _GstAudioAmplifyClass GstAudioAmplifyClass;
 
-typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, guint8 *, guint);
+typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, void *, guint);
 
 struct _GstAudioAmplify
 {
@@ -48,7 +48,8 @@ struct _GstAudioAmplify
   /* < private > */
   GstAudioAmplifyProcessFunc process;
   gint clipping_method;
-  gint format_index;
+  gint format;
+  gint width;
 };
 
 struct _GstAudioAmplifyClass