From 882fd5c387f9f6fa51038e9517c7b0ad665e0b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 10 Aug 2007 04:21:39 +0000 Subject: gst/filter/gstlpwsinc.*: Add a highpass mode. Original commit message from CVS: * gst/filter/gstlpwsinc.c: (gst_lpwsinc_mode_get_type), (gst_lpwsinc_class_init), (process_32), (process_64), (lpwsinc_build_kernel), (lpwsinc_set_property), (lpwsinc_get_property): * gst/filter/gstlpwsinc.h: Add a highpass mode. --- gst/filter/gstlpwsinc.c | 67 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) (limited to 'gst/filter/gstlpwsinc.c') diff --git a/gst/filter/gstlpwsinc.c b/gst/filter/gstlpwsinc.c index 1ba193a9..8f4ec530 100644 --- a/gst/filter/gstlpwsinc.c +++ b/gst/filter/gstlpwsinc.c @@ -29,7 +29,6 @@ * TODO: - Implement the convolution in place, probably only makes sense * when using FFT convolution as currently the convolution itself * is probably the bottleneck. - * - Implement a highpass mode (spectral inversion) * - Allow choosing between different windows (blackman, hanning, ...) * - Maybe allow cascading the filter to get a better stopband attenuation. * Can be done by convolving a filter kernel with itself. @@ -50,10 +49,9 @@ #define GST_CAT_DEFAULT gst_lpwsinc_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); -static const GstElementDetails lpwsinc_details = -GST_ELEMENT_DETAILS ("Low-pass Windowed sinc filter", +static const GstElementDetails lpwsinc_details = GST_ELEMENT_DETAILS ("LPWSinc", "Filter/Effect/Audio", - "Low-pass Windowed sinc filter", + "Low-pass and High-pass Windowed sinc filter", "Thomas , " "Steven W. Smith, " "Dreamlab Technologies Ltd. , " @@ -70,9 +68,36 @@ enum { PROP_0, PROP_LENGTH, - PROP_FREQUENCY + PROP_FREQUENCY, + PROP_MODE }; +enum +{ + MODE_LOW_PASS = 0, + MODE_HIGH_PASS +}; + +#define GST_TYPE_LPWSINC_MODE (gst_lpwsinc_mode_get_type ()) +static GType +gst_lpwsinc_mode_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {MODE_LOW_PASS, "Low pass (default)", + "low-pass"}, + {MODE_HIGH_PASS, "High pass", + "high-pass"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstLPWSincMode", values); + } + return gtype; +} + #define ALLOWED_CAPS \ "audio/x-raw-float," \ " width = (int) { 32, 64 }, " \ @@ -81,7 +106,7 @@ enum " channels = (int) [ 1, MAX ]" #define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_lpwsinc_debug, "lpwsinc", 0, "Low-pass Windowed sinc filter plugin"); + GST_DEBUG_CATEGORY_INIT (gst_lpwsinc_debug, "lpwsinc", 0, "Low-pass and High-pass Windowed sinc filter plugin"); GST_BOILERPLATE_FULL (GstLPWSinc, gst_lpwsinc, GstAudioFilter, GST_TYPE_AUDIO_FILTER, DEBUG_INIT); @@ -147,12 +172,18 @@ gst_lpwsinc_class_init (GstLPWSincClass * klass) g_object_class_install_property (gobject_class, PROP_FREQUENCY, g_param_spec_double ("frequency", "Frequency", - "Cut-off Frequency", 0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE)); + "Cut-off Frequency", 0.0, G_MAXDOUBLE, 0.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); g_object_class_install_property (gobject_class, PROP_LENGTH, g_param_spec_int ("length", "Length", "N such that the filter length = 2N + 1", - 1, G_MAXINT, 1, G_PARAM_READWRITE)); + 1, G_MAXINT, 1, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", + "Low pass or high pass mode", GST_TYPE_LPWSINC_MODE, + MODE_LOW_PASS, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); trans_class->transform = GST_DEBUG_FUNCPTR (lpwsinc_transform); trans_class->get_unit_size = GST_DEBUG_FUNCPTR (lpwsinc_get_unit_size); @@ -173,7 +204,7 @@ gst_lpwsinc_init (GstLPWSinc * self, GstLPWSincClass * g_class) static void process_32 (GstLPWSinc * self, gfloat * src, gfloat * dst, guint input_samples) { - gint kernel_length = self->wing_size * 2 + 1;; + gint kernel_length = self->wing_size * 2 + 1; gint i, j, k, l; gint channels = GST_AUDIO_FILTER (self)->format.channels; @@ -200,7 +231,7 @@ static void process_64 (GstLPWSinc * self, gdouble * src, gdouble * dst, guint input_samples) { - gint kernel_length = self->wing_size * 2 + 1;; + gint kernel_length = self->wing_size * 2 + 1; gint i, j, k, l; gint channels = GST_AUDIO_FILTER (self)->format.channels; @@ -270,6 +301,13 @@ lpwsinc_build_kernel (GstLPWSinc * self) for (i = 0; i <= len * 2; ++i) self->kernel[i] /= sum; + /* convert to highpass if specified */ + if (self->mode == MODE_HIGH_PASS) { + for (i = 0; i <= len * 2; ++i) + self->kernel[i] = -self->kernel[i]; + self->kernel[len] += 1.0; + } + /* set up the residue memory space */ if (self->residue) g_free (self->residue); @@ -370,6 +408,12 @@ lpwsinc_set_property (GObject * object, guint prop_id, const GValue * value, lpwsinc_build_kernel (self); GST_BASE_TRANSFORM_UNLOCK (self); break; + case PROP_MODE: + GST_BASE_TRANSFORM_LOCK (self); + self->mode = g_value_get_enum (value); + lpwsinc_build_kernel (self); + GST_BASE_TRANSFORM_UNLOCK (self); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -389,6 +433,9 @@ lpwsinc_get_property (GObject * object, guint prop_id, GValue * value, case PROP_FREQUENCY: g_value_set_double (value, self->frequency); break; + case PROP_MODE: + g_value_set_enum (value, self->mode); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; -- cgit v1.2.1