mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 04:00:37 +00:00
gst/filter/gstlpwsinc.*: Specify the actual filter length instead of a weird 2N+1. Setting the property will round to...
Original commit message from CVS: * gst/filter/gstlpwsinc.c: (gst_lpwsinc_class_init), (gst_lpwsinc_init), (process_32), (process_64), (lpwsinc_build_kernel), (lpwsinc_set_property), (lpwsinc_get_property): * gst/filter/gstlpwsinc.h: Specify the actual filter length instead of a weird 2N+1. Setting the property will round to the next odd number. Also remove now obsolete FIXMEs.
This commit is contained in:
parent
982bf23b35
commit
11131b7a44
3 changed files with 40 additions and 28 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2007-08-10 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
|
* gst/filter/gstlpwsinc.c: (gst_lpwsinc_class_init),
|
||||||
|
(gst_lpwsinc_init), (process_32), (process_64),
|
||||||
|
(lpwsinc_build_kernel), (lpwsinc_set_property),
|
||||||
|
(lpwsinc_get_property):
|
||||||
|
* gst/filter/gstlpwsinc.h:
|
||||||
|
Specify the actual filter length instead of a weird
|
||||||
|
2N+1. Setting the property will round to the next odd number.
|
||||||
|
Also remove now obsolete FIXMEs.
|
||||||
|
|
||||||
2007-08-10 Sebastian Dröge <slomo@circular-chaos.org>
|
2007-08-10 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
* gst/filter/gstlpwsinc.c: (gst_lpwsinc_window_get_type),
|
* gst/filter/gstlpwsinc.c: (gst_lpwsinc_window_get_type),
|
||||||
|
|
|
@ -204,8 +204,8 @@ gst_lpwsinc_class_init (GstLPWSincClass * klass)
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LENGTH,
|
g_object_class_install_property (gobject_class, PROP_LENGTH,
|
||||||
g_param_spec_int ("length", "Length",
|
g_param_spec_int ("length", "Length",
|
||||||
"N such that the filter length = 2N + 1",
|
"Filter kernel length, will be rounded to the next odd number",
|
||||||
1, G_MAXINT, 1, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
3, G_MAXINT, 101, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_MODE,
|
g_object_class_install_property (gobject_class, PROP_MODE,
|
||||||
g_param_spec_enum ("mode", "Mode",
|
g_param_spec_enum ("mode", "Mode",
|
||||||
|
@ -227,7 +227,7 @@ gst_lpwsinc_init (GstLPWSinc * self, GstLPWSincClass * g_class)
|
||||||
{
|
{
|
||||||
self->mode = MODE_LOW_PASS;
|
self->mode = MODE_LOW_PASS;
|
||||||
self->window = WINDOW_HAMMING;
|
self->window = WINDOW_HAMMING;
|
||||||
self->wing_size = 50;
|
self->kernel_length = 101;
|
||||||
self->frequency = 0.0;
|
self->frequency = 0.0;
|
||||||
self->kernel = NULL;
|
self->kernel = NULL;
|
||||||
self->residue = NULL;
|
self->residue = NULL;
|
||||||
|
@ -238,7 +238,7 @@ gst_lpwsinc_init (GstLPWSinc * self, GstLPWSincClass * g_class)
|
||||||
static void
|
static void
|
||||||
process_32 (GstLPWSinc * self, gfloat * src, gfloat * dst, guint input_samples)
|
process_32 (GstLPWSinc * self, gfloat * src, gfloat * dst, guint input_samples)
|
||||||
{
|
{
|
||||||
gint kernel_length = self->wing_size * 2 + 1;
|
gint kernel_length = self->kernel_length;
|
||||||
gint i, j, k, l;
|
gint i, j, k, l;
|
||||||
gint channels = GST_AUDIO_FILTER (self)->format.channels;
|
gint channels = GST_AUDIO_FILTER (self)->format.channels;
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ static void
|
||||||
process_64 (GstLPWSinc * self, gdouble * src, gdouble * dst,
|
process_64 (GstLPWSinc * self, gdouble * src, gdouble * dst,
|
||||||
guint input_samples)
|
guint input_samples)
|
||||||
{
|
{
|
||||||
gint kernel_length = self->wing_size * 2 + 1;
|
gint kernel_length = self->kernel_length;
|
||||||
gint i, j, k, l;
|
gint i, j, k, l;
|
||||||
gint channels = GST_AUDIO_FILTER (self)->format.channels;
|
gint channels = GST_AUDIO_FILTER (self)->format.channels;
|
||||||
|
|
||||||
|
@ -297,8 +297,8 @@ lpwsinc_build_kernel (GstLPWSinc * self)
|
||||||
gdouble w;
|
gdouble w;
|
||||||
|
|
||||||
/* fill the kernel */
|
/* fill the kernel */
|
||||||
len = self->wing_size;
|
len = self->kernel_length;
|
||||||
GST_DEBUG ("lpwsinc: initializing filter kernel of length %d", len * 2 + 1);
|
GST_DEBUG ("lpwsinc: initializing filter kernel of length %d", len);
|
||||||
|
|
||||||
if (GST_AUDIO_FILTER (self)->format.rate == 0) {
|
if (GST_AUDIO_FILTER (self)->format.rate == 0) {
|
||||||
GST_DEBUG ("rate not set yet");
|
GST_DEBUG ("rate not set yet");
|
||||||
|
@ -318,40 +318,40 @@ lpwsinc_build_kernel (GstLPWSinc * self)
|
||||||
|
|
||||||
if (self->kernel)
|
if (self->kernel)
|
||||||
g_free (self->kernel);
|
g_free (self->kernel);
|
||||||
self->kernel = g_new (gdouble, 2 * len + 1);
|
self->kernel = g_new (gdouble, len);
|
||||||
|
|
||||||
for (i = 0; i <= len * 2; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
if (i == len)
|
if (i == len / 2)
|
||||||
self->kernel[i] = w;
|
self->kernel[i] = w;
|
||||||
else
|
else
|
||||||
self->kernel[i] = sin (w * (i - len)) / (i - len);
|
self->kernel[i] = sin (w * (i - len / 2)) / (i - len / 2);
|
||||||
/* windowing */
|
/* windowing */
|
||||||
if (self->window == WINDOW_HAMMING)
|
if (self->window == WINDOW_HAMMING)
|
||||||
self->kernel[i] *= (0.54 - 0.46 * cos (M_PI * i / len));
|
self->kernel[i] *= (0.54 - 0.46 * cos (2 * M_PI * i / len));
|
||||||
else
|
else
|
||||||
self->kernel[i] *=
|
self->kernel[i] *=
|
||||||
(0.42 - 0.5 * cos (M_PI * i / len) + 0.08 * cos (2 * M_PI * i / len));
|
(0.42 - 0.5 * cos (2 * M_PI * i / len) +
|
||||||
|
0.08 * cos (4 * M_PI * i / len));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* normalize for unity gain at DC */
|
/* normalize for unity gain at DC */
|
||||||
for (i = 0; i <= len * 2; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
sum += self->kernel[i];
|
sum += self->kernel[i];
|
||||||
for (i = 0; i <= len * 2; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
self->kernel[i] /= sum;
|
self->kernel[i] /= sum;
|
||||||
|
|
||||||
/* convert to highpass if specified */
|
/* convert to highpass if specified */
|
||||||
if (self->mode == MODE_HIGH_PASS) {
|
if (self->mode == MODE_HIGH_PASS) {
|
||||||
for (i = 0; i <= len * 2; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
self->kernel[i] = -self->kernel[i];
|
self->kernel[i] = -self->kernel[i];
|
||||||
self->kernel[len] += 1.0;
|
self->kernel[len / 2] += 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up the residue memory space */
|
/* set up the residue memory space */
|
||||||
if (self->residue)
|
if (self->residue)
|
||||||
g_free (self->residue);
|
g_free (self->residue);
|
||||||
self->residue =
|
self->residue =
|
||||||
g_new0 (gdouble,
|
g_new0 (gdouble, len * GST_AUDIO_FILTER (self)->format.channels);
|
||||||
(len * 2 + 1) * GST_AUDIO_FILTER (self)->format.channels);
|
|
||||||
|
|
||||||
self->have_kernel = TRUE;
|
self->have_kernel = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -434,12 +434,18 @@ lpwsinc_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||||
g_return_if_fail (GST_IS_LPWSINC (self));
|
g_return_if_fail (GST_IS_LPWSINC (self));
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_LENGTH:
|
case PROP_LENGTH:{
|
||||||
|
gint val;
|
||||||
|
|
||||||
GST_BASE_TRANSFORM_LOCK (self);
|
GST_BASE_TRANSFORM_LOCK (self);
|
||||||
self->wing_size = g_value_get_int (value);
|
val = g_value_get_int (value);
|
||||||
|
if (val % 2 == 0)
|
||||||
|
val++;
|
||||||
|
self->kernel_length = val;
|
||||||
lpwsinc_build_kernel (self);
|
lpwsinc_build_kernel (self);
|
||||||
GST_BASE_TRANSFORM_UNLOCK (self);
|
GST_BASE_TRANSFORM_UNLOCK (self);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case PROP_FREQUENCY:
|
case PROP_FREQUENCY:
|
||||||
GST_BASE_TRANSFORM_LOCK (self);
|
GST_BASE_TRANSFORM_LOCK (self);
|
||||||
self->frequency = g_value_get_double (value);
|
self->frequency = g_value_get_double (value);
|
||||||
|
@ -472,7 +478,7 @@ lpwsinc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_LENGTH:
|
case PROP_LENGTH:
|
||||||
g_value_set_int (value, self->wing_size);
|
g_value_set_int (value, self->kernel_length);
|
||||||
break;
|
break;
|
||||||
case PROP_FREQUENCY:
|
case PROP_FREQUENCY:
|
||||||
g_value_set_double (value, self->frequency);
|
g_value_set_double (value, self->frequency);
|
||||||
|
|
|
@ -25,10 +25,6 @@
|
||||||
* chapter 16
|
* chapter 16
|
||||||
* available at http://www.dspguide.com/
|
* available at http://www.dspguide.com/
|
||||||
*
|
*
|
||||||
* FIXME:
|
|
||||||
* - this filter is totally unoptimized !
|
|
||||||
* - we do not destroy the allocated memory for filters and residue
|
|
||||||
* - this might be improved upon with bytestream
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GST_LPWSINC_H__
|
#ifndef __GST_LPWSINC_H__
|
||||||
|
@ -69,8 +65,7 @@ struct _GstLPWSinc {
|
||||||
gint mode;
|
gint mode;
|
||||||
gint window;
|
gint window;
|
||||||
gdouble frequency;
|
gdouble frequency;
|
||||||
gint wing_size; /* length of a "wing" of the filter;
|
gint kernel_length; /* length of the filter kernel */
|
||||||
actual length is 2 * wing_size + 1 */
|
|
||||||
|
|
||||||
gdouble *residue; /* buffer for left-over samples from previous buffer */
|
gdouble *residue; /* buffer for left-over samples from previous buffer */
|
||||||
gdouble *kernel; /* filter kernel */
|
gdouble *kernel; /* filter kernel */
|
||||||
|
|
Loading…
Reference in a new issue