summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--gst/filter/gstbpwsinc.c121
-rw-r--r--gst/filter/gstbpwsinc.h3
-rw-r--r--gst/filter/gstlpwsinc.c3
4 files changed, 123 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 4c3f5bd2..443b77ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2007-08-10 Sebastian Dröge <slomo@circular-chaos.org>
+ * gst/filter/gstbpwsinc.c: (gst_bpwsinc_mode_get_type),
+ (gst_bpwsinc_window_get_type), (gst_bpwsinc_class_init),
+ (gst_bpwsinc_init), (bpwsinc_build_kernel), (bpwsinc_set_property),
+ (bpwsinc_get_property):
+ * gst/filter/gstbpwsinc.h:
+ Add support for a bandreject mode and allow specifying the window
+ function that should be used.
+ * gst/filter/gstlpwsinc.c:
+ And another small formatting fix.
+
+2007-08-10 Sebastian Dröge <slomo@circular-chaos.org>
+
* gst/filter/gstbpwsinc.c: (gst_bpwsinc_class_init),
(gst_bpwsinc_init), (process_32), (process_64),
(bpwsinc_build_kernel), (bpwsinc_setup), (bpwsinc_get_unit_size),
diff --git a/gst/filter/gstbpwsinc.c b/gst/filter/gstbpwsinc.c
index 15e35bee..dcf7c68f 100644
--- a/gst/filter/gstbpwsinc.c
+++ b/gst/filter/gstbpwsinc.c
@@ -29,8 +29,8 @@
* 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 band reject 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
*/
#ifdef HAVE_CONFIG_H
@@ -69,9 +69,63 @@ enum
PROP_0,
PROP_LENGTH,
PROP_LOWER_FREQUENCY,
- PROP_UPPER_FREQUENCY
+ PROP_UPPER_FREQUENCY,
+ PROP_MODE,
+ PROP_WINDOW
};
+enum
+{
+ MODE_BAND_PASS = 0,
+ MODE_BAND_REJECT
+};
+
+#define GST_TYPE_BPWSINC_MODE (gst_bpwsinc_mode_get_type ())
+static GType
+gst_bpwsinc_mode_get_type (void)
+{
+ static GType gtype = 0;
+
+ if (gtype == 0) {
+ static const GEnumValue values[] = {
+ {MODE_BAND_PASS, "Band pass (default)",
+ "band-pass"},
+ {MODE_BAND_REJECT, "Band reject",
+ "band-reject"},
+ {0, NULL, NULL}
+ };
+
+ gtype = g_enum_register_static ("GstBPWSincMode", values);
+ }
+ return gtype;
+}
+
+enum
+{
+ WINDOW_HAMMING = 0,
+ WINDOW_BLACKMAN
+};
+
+#define GST_TYPE_BPWSINC_WINDOW (gst_bpwsinc_window_get_type ())
+static GType
+gst_bpwsinc_window_get_type (void)
+{
+ static GType gtype = 0;
+
+ if (gtype == 0) {
+ static const GEnumValue values[] = {
+ {WINDOW_HAMMING, "Hamming window (default)",
+ "hamming"},
+ {WINDOW_BLACKMAN, "Blackman window",
+ "blackman"},
+ {0, NULL, NULL}
+ };
+
+ gtype = g_enum_register_static ("GstBPWSincWindow", values);
+ }
+ return gtype;
+}
+
#define ALLOWED_CAPS \
"audio/x-raw-float, " \
" width = (int) { 32, 64 }, " \
@@ -157,6 +211,16 @@ gst_bpwsinc_class_init (GstBPWSincClass * klass)
"Filter kernel length, will be rounded to the next odd number",
3, G_MAXINT, 101, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_MODE,
+ g_param_spec_enum ("mode", "Mode",
+ "Band pass or band reject mode", GST_TYPE_BPWSINC_MODE,
+ MODE_BAND_PASS, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
+ g_object_class_install_property (gobject_class, PROP_WINDOW,
+ g_param_spec_enum ("window", "Window",
+ "Window function to use", GST_TYPE_BPWSINC_WINDOW,
+ WINDOW_HAMMING, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
trans_class->transform = GST_DEBUG_FUNCPTR (bpwsinc_transform);
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (bpwsinc_get_unit_size);
GST_AUDIO_FILTER_CLASS (klass)->setup = GST_DEBUG_FUNCPTR (bpwsinc_setup);
@@ -168,6 +232,8 @@ gst_bpwsinc_init (GstBPWSinc * self, GstBPWSincClass * g_class)
self->kernel_length = 101;
self->lower_frequency = 0.0;
self->upper_frequency = 0.0;
+ self->mode = MODE_BAND_PASS;
+ self->window = WINDOW_HAMMING;
self->kernel = NULL;
self->have_kernel = FALSE;
self->residue = NULL;
@@ -273,9 +339,13 @@ bpwsinc_build_kernel (GstBPWSinc * self)
else
kernel_lp[i] = sin (w * (i - len / 2))
/ (i - len / 2);
- /* Blackman windowing */
- kernel_lp[i] *= (0.42 - 0.5 * cos (2 * M_PI * i / len)
- + 0.08 * cos (4 * M_PI * i / len));
+ /* Windowing */
+ if (self->window == WINDOW_HAMMING)
+ kernel_lp[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
+ else
+ kernel_lp[i] *=
+ (0.42 - 0.5 * cos (2 * M_PI * i / len) +
+ 0.08 * cos (4 * M_PI * i / len));
}
/* normalize for unity gain at DC */
@@ -297,9 +367,13 @@ bpwsinc_build_kernel (GstBPWSinc * self)
else
kernel_hp[i] = sin (w * (i - len / 2))
/ (i - len / 2);
- /* Blackman windowing */
- kernel_hp[i] *= (0.42 - 0.5 * cos (2 * M_PI * i / len)
- + 0.08 * cos (4 * M_PI * i / len));
+ /* Windowing */
+ if (self->window == WINDOW_HAMMING)
+ kernel_hp[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
+ else
+ kernel_hp[i] *=
+ (0.42 - 0.5 * cos (2 * M_PI * i / len) +
+ 0.08 * cos (4 * M_PI * i / len));
}
/* normalize for unity gain at DC */
@@ -326,10 +400,13 @@ bpwsinc_build_kernel (GstBPWSinc * self)
g_free (kernel_lp);
g_free (kernel_hp);
- /* do spectral inversion to go from bandreject to bandpass */
- for (i = 0; i < len; ++i)
- self->kernel[i] = -self->kernel[i];
- self->kernel[len / 2] += 1;
+ /* do spectral inversion to go from bandreject to bandpass
+ * if specified */
+ if (self->mode == MODE_BAND_PASS) {
+ for (i = 0; i < len; ++i)
+ self->kernel[i] = -self->kernel[i];
+ self->kernel[len / 2] += 1;
+ }
/* set up the residue memory space */
if (self->residue)
@@ -441,6 +518,18 @@ bpwsinc_set_property (GObject * object, guint prop_id, const GValue * value,
bpwsinc_build_kernel (self);
GST_BASE_TRANSFORM_UNLOCK (self);
break;
+ case PROP_MODE:
+ GST_BASE_TRANSFORM_LOCK (self);
+ self->mode = g_value_get_enum (value);
+ bpwsinc_build_kernel (self);
+ GST_BASE_TRANSFORM_UNLOCK (self);
+ break;
+ case PROP_WINDOW:
+ GST_BASE_TRANSFORM_LOCK (self);
+ self->window = g_value_get_enum (value);
+ bpwsinc_build_kernel (self);
+ GST_BASE_TRANSFORM_UNLOCK (self);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -463,6 +552,12 @@ bpwsinc_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_UPPER_FREQUENCY:
g_value_set_double (value, self->upper_frequency);
break;
+ case PROP_MODE:
+ g_value_set_enum (value, self->mode);
+ break;
+ case PROP_WINDOW:
+ g_value_set_enum (value, self->window);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/gst/filter/gstbpwsinc.h b/gst/filter/gstbpwsinc.h
index 3bbb3e01..537c2f6d 100644
--- a/gst/filter/gstbpwsinc.h
+++ b/gst/filter/gstbpwsinc.h
@@ -62,7 +62,8 @@ struct _GstBPWSinc {
GstBPWSincProcessFunc process;
- gdouble frequency;
+ gint mode;
+ gint window;
gdouble lower_frequency, upper_frequency;
gint kernel_length; /* length of the filter kernel */
diff --git a/gst/filter/gstlpwsinc.c b/gst/filter/gstlpwsinc.c
index 2debfe77..f6393169 100644
--- a/gst/filter/gstlpwsinc.c
+++ b/gst/filter/gstlpwsinc.c
@@ -28,7 +28,7 @@
*
* TODO: - Implement the convolution in place, probably only makes sense
* when using FFT convolution as currently the convolution itself
- * is probably the bottleneck.
+ * is probably the bottleneck
* - Maybe allow cascading the filter to get a better stopband attenuation.
* Can be done by convolving a filter kernel with itself.
*/
@@ -124,7 +124,6 @@ gst_lpwsinc_window_get_type (void)
return gtype;
}
-
#define ALLOWED_CAPS \
"audio/x-raw-float, " \
" width = (int) { 32, 64 }, " \