diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | gst/filter/gstlpwsinc.c | 67 | ||||
-rw-r--r-- | gst/filter/gstlpwsinc.h | 1 |
3 files changed, 67 insertions, 10 deletions
@@ -1,5 +1,14 @@ 2007-08-10 Sebastian Dröge <slomo@circular-chaos.org> + * 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. + +2007-08-10 Sebastian Dröge <slomo@circular-chaos.org> + * gst/filter/gstlpwsinc.c: (process_32), (process_64), (lpwsinc_build_kernel): Fix processing if the input has more than one channel. 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 <thomas@apestaart.org>, " "Steven W. Smith, " "Dreamlab Technologies Ltd. <mathis.hofer@dreamlab.net>, " @@ -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; diff --git a/gst/filter/gstlpwsinc.h b/gst/filter/gstlpwsinc.h index afb7e9c7..bc9377f6 100644 --- a/gst/filter/gstlpwsinc.h +++ b/gst/filter/gstlpwsinc.h @@ -66,6 +66,7 @@ struct _GstLPWSinc { GstLPWSincProcessFunc process; + gint mode; gdouble frequency; gint wing_size; /* length of a "wing" of the filter; actual length is 2 * wing_size + 1 */ |