Commit 85e572a4 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵
Browse files

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.
parent 0e4fc665
......@@ -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;
......
......@@ -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 */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment