summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKipp Cannon <kcannon@ligo.caltech.edu>2009-06-19 22:20:45 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-06-19 22:20:45 +0200
commitafccf53acee778b057f4f4bae19a41397fe8ff36 (patch)
tree36f668ee244dd704eeee9921510784603a56311c
parent8ecd5f1a06537c856e69a78b2fd44cf4d02571f4 (diff)
audioamplify: Add noclip method and support for more formats
Fixes bug #585828 and #585831.
-rw-r--r--gst/audiofx/audioamplify.c393
-rw-r--r--gst/audiofx/audioamplify.h5
2 files changed, 233 insertions, 165 deletions
diff --git a/gst/audiofx/audioamplify.c b/gst/audiofx/audioamplify.c
index da5412a48..9e33e552c 100644
--- a/gst/audiofx/audioamplify.c
+++ b/gst/audiofx/audioamplify.c
@@ -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 */
diff --git a/gst/audiofx/audioamplify.h b/gst/audiofx/audioamplify.h
index 4924814f0..b28f38b3c 100644
--- a/gst/audiofx/audioamplify.h
+++ b/gst/audiofx/audioamplify.h
@@ -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