From afccf53acee778b057f4f4bae19a41397fe8ff36 Mon Sep 17 00:00:00 2001 From: Kipp Cannon Date: Fri, 19 Jun 2009 22:20:45 +0200 Subject: audioamplify: Add noclip method and support for more formats Fixes bug #585828 and #585831. --- gst/audiofx/audioamplify.c | 393 ++++++++++++++++++++++++++------------------- gst/audiofx/audioamplify.h | 5 +- 2 files changed, 233 insertions(+), 165 deletions(-) (limited to 'gst/audiofx') diff --git a/gst/audiofx/audioamplify.c b/gst/audiofx/audioamplify.c index da5412a4..9e33e552 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 4924814f..b28f38b3 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 -- cgit