freeverb: port to 1.0

This commit is contained in:
Stefan Sauer 2013-02-07 08:41:25 +01:00
parent 09764eca37
commit 998cfde158
4 changed files with 110 additions and 135 deletions

View file

@ -317,7 +317,6 @@ dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED=" aiff \
cdxaparse \
dccp faceoverlay \
freeverb \
hdvparse ivfparse jp2kdecimator \
kate librfb \
mve mythtv nsf nuvdemux \

View file

@ -5,8 +5,14 @@ libgstfreeverb_la_SOURCES = gstfreeverb.c
# flags used to compile this plugin
# add other _CFLAGS and _LIBS as needed
libgstfreeverb_la_CFLAGS = $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS)
libgstfreeverb_la_LIBADD = $(GST_BASE_LIBS) $(GST_CONTROLLER_LIBS) $(GST_LIBS)
libgstfreeverb_la_CFLAGS = $(GST_CFLAGS) \
$(GST_BASE_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS)
libgstfreeverb_la_LIBADD = $(GST_LIBS) \
$(GST_BASE_LIBS) \
$(GST_PLUGINS_BASE_LIBS) \
-lgstaudio-$(GST_API_VERSION) \
$(LIBM)
libgstfreeverb_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstfreeverb_la_LIBTOOLFLAGS = --tag=disable-static

View file

@ -52,10 +52,10 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
#include <gst/controller/gstcontroller.h>
#include "gstfreeverb.h"
@ -74,41 +74,27 @@ enum
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-float, "
"rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, 2 ], "
"endianness = (int) BYTE_ORDER, " "width = (int) 32; "
"audio/x-raw-int, "
"rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, 2 ], "
"endianness = (int) BYTE_ORDER, "
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) { " GST_AUDIO_NE (F32) ", " GST_AUDIO_NE (S16) "}, "
"rate = (int) [ 1, MAX ], " "channels = (int) 1, "
"layout = (string) interleaved;"
"audio/x-raw, "
"format = (string) { " GST_AUDIO_NE (F32) ", " GST_AUDIO_NE (S16) "}, "
"rate = (int) [ 1, MAX ], " "channels = (int) 2, "
"layout = (string) interleaved, " "channel-mask = (bitmask) 0x3")
);
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-float, "
"rate = (int) [ 1, MAX ], "
"channels = (int) 2, "
"endianness = (int) BYTE_ORDER, " "width = (int) 32; "
"audio/x-raw-int, "
"rate = (int) [ 1, MAX ], "
"channels = (int) 2, "
"endianness = (int) BYTE_ORDER, "
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) { " GST_AUDIO_NE (F32) ", " GST_AUDIO_NE (S16) "}, "
"rate = (int) [ 1, MAX ], " "channels = (int) 2, "
"layout = (string) interleaved, " "channel-mask = (bitmask) 0x3")
);
#define _do_init(type) { \
const GInterfaceInfo preset_interface_info = { NULL, NULL, NULL }; \
g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_interface_info); \
\
GST_DEBUG_CATEGORY_INIT (gst_freeverb_debug, "freeverb", 0, \
"freeverb element"); \
}
GST_BOILERPLATE_FULL (GstFreeverb, gst_freeverb, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, _do_init);
G_DEFINE_TYPE_WITH_CODE (GstFreeverb, gst_freeverb, GST_TYPE_BASE_TRANSFORM,
G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
static void gst_freeverb_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@ -118,9 +104,9 @@ static void gst_freeverb_get_property (GObject * object, guint prop_id,
static void gst_freeverb_finalize (GObject * object);
static gboolean gst_freeverb_get_unit_size (GstBaseTransform * base,
GstCaps * caps, guint * size);
GstCaps * caps, gsize * size);
static GstCaps *gst_freeverb_transform_caps (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps);
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
static gboolean gst_freeverb_set_caps (GstBaseTransform * base,
GstCaps * incaps, GstCaps * outcaps);
@ -399,28 +385,20 @@ freeverb_revmodel_free (GstFreeverb * filter)
/* GObject vmethod implementations */
static void
gst_freeverb_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
gst_element_class_set_static_metadata (element_class, "Stereo positioning",
"Filter/Effect/Audio",
"Reverberation/room effect", "Stefan Sauer <ensonic@users.sf.net>");
}
static void
gst_freeverb_class_init (GstFreeverbClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *element_class;
g_type_class_add_private (klass, sizeof (GstFreeverbPrivate));
GST_DEBUG_CATEGORY_INIT (gst_freeverb_debug, "freeverb", 0,
"freeverb element");
gobject_class = (GObjectClass *) klass;
element_class = (GstElementClass *) klass;
gobject_class->set_property = gst_freeverb_set_property;
gobject_class->get_property = gst_freeverb_get_property;
gobject_class->finalize = gst_freeverb_finalize;
@ -445,6 +423,16 @@ gst_freeverb_class_init (GstFreeverbClass * klass)
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
G_PARAM_STATIC_STRINGS));
gst_element_class_set_static_metadata (element_class,
"Reverberation/room effect", "Filter/Effect/Audio",
"Add reverberation to audio streams",
"Stefan Sauer <ensonic@users.sf.net>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
GST_DEBUG_FUNCPTR (gst_freeverb_get_unit_size);
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
@ -456,15 +444,13 @@ gst_freeverb_class_init (GstFreeverbClass * klass)
}
static void
gst_freeverb_init (GstFreeverb * filter, GstFreeverbClass * klass)
gst_freeverb_init (GstFreeverb * filter)
{
filter->priv =
G_TYPE_INSTANCE_GET_PRIVATE (filter, GST_TYPE_FREEVERB,
GstFreeverbPrivate);
filter->width = 0;
filter->channels = 0;
filter->format_float = FALSE;
gst_audio_info_init (&filter->info);
filter->process = NULL;
gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
@ -479,33 +465,32 @@ gst_freeverb_finalize (GObject * object)
freeverb_revmodel_free (filter);
G_OBJECT_CLASS (parent_class)->finalize (object);
G_OBJECT_CLASS (gst_freeverb_parent_class)->finalize (object);
}
static gboolean
gst_freeverb_set_process_function (GstFreeverb * filter)
gst_freeverb_set_process_function (GstFreeverb * filter, GstAudioInfo * info)
{
gint channel_index, format_index;
const GstAudioFormatInfo *finfo = info->finfo;
/* set processing function */
channel_index = filter->channels - 1;
channel_index = GST_AUDIO_INFO_CHANNELS (info) - 1;
if (channel_index > 1 || channel_index < 0) {
filter->process = NULL;
return FALSE;
}
format_index = (filter->format_float) ? 1 : 0;
format_index = GST_AUDIO_FORMAT_INFO_IS_FLOAT (finfo) ? 1 : 0;
filter->process = process_functions[channel_index][format_index];
g_assert (filter->process);
return TRUE;
}
static void
gst_freeverb_init_rev_model (GstFreeverb * filter)
{
gfloat srfactor = filter->rate / 44100.0f;
gfloat srfactor = GST_AUDIO_INFO_RATE (&filter->info) / 44100.0f;
GstFreeverbPrivate *priv = filter->priv;
freeverb_revmodel_free (filter);
@ -624,43 +609,54 @@ gst_freeverb_get_property (GObject * object, guint prop_id,
static gboolean
gst_freeverb_get_unit_size (GstBaseTransform * base, GstCaps * caps,
guint * size)
gsize * size)
{
gint width, channels;
GstStructure *structure;
gboolean ret;
GstAudioInfo info;
g_assert (size);
/* this works for both float and int */
structure = gst_caps_get_structure (caps, 0);
ret = gst_structure_get_int (structure, "width", &width);
ret &= gst_structure_get_int (structure, "channels", &channels);
if (!gst_audio_info_from_caps (&info, caps))
return FALSE;
*size = width * channels / 8;
*size = GST_AUDIO_INFO_BPF (&info);
GST_INFO_OBJECT (base, "unit size: %u", *size);
return ret;
return TRUE;
}
static GstCaps *
gst_freeverb_transform_caps (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps)
GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
GstCaps *res;
GstStructure *structure;
gint i;
/* transform caps gives one single caps so we can just replace
* the channel property with our range. */
/* replace the channel property with our range. */
res = gst_caps_copy (caps);
structure = gst_caps_get_structure (res, 0);
if (direction == GST_PAD_SRC) {
GST_INFO_OBJECT (base, "allow 1-2 channels");
gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
} else {
GST_INFO_OBJECT (base, "allow 2 channels");
gst_structure_set (structure, "channels", G_TYPE_INT, 2, NULL);
for (i = 0; i < gst_caps_get_size (res); i++) {
structure = gst_caps_get_structure (res, i);
if (direction == GST_PAD_SRC) {
GST_INFO_OBJECT (base, "[%d] allow 1-2 channels", i);
gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
gst_structure_remove_field (structure, "channel-mask");
} else {
GST_INFO_OBJECT (base, "[%d] allow 2 channels", i);
gst_structure_set (structure, "channels", G_TYPE_INT, 2, NULL);
}
}
GST_DEBUG_OBJECT (base, "transformed %" GST_PTR_FORMAT, res);
if (filter) {
GstCaps *intersection;
GST_DEBUG_OBJECT (base, "Using filter caps %" GST_PTR_FORMAT, filter);
intersection =
gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (res);
res = intersection;
GST_DEBUG_OBJECT (base, "Intersection %" GST_PTR_FORMAT, res);
}
return res;
@ -671,57 +667,28 @@ gst_freeverb_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps)
{
GstFreeverb *filter = GST_FREEVERB (base);
const GstStructure *structure;
gboolean ret;
gint width, rate;
const gchar *fmt;
GstAudioInfo info;
/*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */
if (!gst_audio_info_from_caps (&info, incaps))
goto no_format;
structure = gst_caps_get_structure (incaps, 0);
ret = gst_structure_get_int (structure, "channels", &filter->channels);
if (!ret)
goto no_channels;
if (!gst_freeverb_set_process_function (filter, &info))
goto no_format;
ret = gst_structure_get_int (structure, "width", &width);
if (!ret)
goto no_width;
filter->width = width / 8;
ret = gst_structure_get_int (structure, "rate", &rate);
if (!ret)
goto no_rate;
filter->rate = rate;
fmt = gst_structure_get_name (structure);
if (!strcmp (fmt, "audio/x-raw-int"))
filter->format_float = FALSE;
else
filter->format_float = TRUE;
GST_DEBUG_OBJECT (filter, "try to process %s input_1 with %d channels", fmt,
filter->channels);
ret = gst_freeverb_set_process_function (filter);
if (!ret)
GST_WARNING_OBJECT (filter, "can't process input_1 with %d channels",
filter->channels);
filter->info = info;
gst_freeverb_init_rev_model (filter);
filter->drained = FALSE;
GST_INFO_OBJECT (base, "model configured");
return ret;
return TRUE;
no_channels:
GST_DEBUG_OBJECT (filter, "no channels in caps");
return ret;
no_width:
GST_DEBUG_OBJECT (filter, "no width in caps");
return ret;
no_rate:
GST_DEBUG_OBJECT (filter, "no rate in caps");
return ret;
no_format:
{
GST_DEBUG ("invalid caps");
return FALSE;
}
}
static gboolean
@ -919,39 +886,47 @@ gst_freeverb_transform (GstBaseTransform * base, GstBuffer * inbuf,
GstBuffer * outbuf)
{
GstFreeverb *filter = GST_FREEVERB (base);
guint num_samples = GST_BUFFER_SIZE (outbuf) / (2 * filter->width);
guint num_samples;
GstClockTime timestamp;
GstMapInfo inmap, outmap;
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
timestamp =
gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
gst_buffer_map (inbuf, &inmap, GST_MAP_READ);
gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
num_samples = outmap.size / (2 * GST_AUDIO_INFO_BPS (&filter->info));
GST_DEBUG_OBJECT (filter, "processing %u samples at %" GST_TIME_FORMAT,
num_samples, GST_TIME_ARGS (timestamp));
if (GST_CLOCK_TIME_IS_VALID (timestamp))
gst_object_sync_values (G_OBJECT (filter), timestamp);
gst_object_sync_values (GST_OBJECT (filter), timestamp);
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT))) {
filter->drained = FALSE;
}
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))) {
if (filter->drained) {
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
return GST_FLOW_OK;
memset (outmap.data, 0, outmap.size);
}
} else {
filter->drained = FALSE;
}
filter->drained = filter->process (filter, GST_BUFFER_DATA (inbuf),
GST_BUFFER_DATA (outbuf), num_samples);
if (!filter->drained) {
filter->drained =
filter->process (filter, inmap.data, outmap.data, num_samples);
}
if (filter->drained) {
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
}
gst_buffer_unmap (inbuf, &inmap);
gst_buffer_unmap (outbuf, &outmap);
return GST_FLOW_OK;
}
@ -959,8 +934,6 @@ gst_freeverb_transform (GstBaseTransform * base, GstBuffer * inbuf,
static gboolean
plugin_init (GstPlugin * plugin)
{
gst_controller_init (NULL, NULL);
return gst_element_register (plugin, "freeverb",
GST_RANK_NONE, GST_TYPE_FREEVERB);
}

View file

@ -22,6 +22,7 @@
#define __GST_FREEVERB_H__
#include <gst/gst.h>
#include <gst/audio/audio.h>
#include <gst/base/gstbasetransform.h>
G_BEGIN_DECLS
@ -49,12 +50,8 @@ struct _GstFreeverb {
gfloat level;
GstFreeverbProcessFunc process;
gint channels;
gboolean format_float;
gint width;
gint method;
gint rate;
GstAudioInfo info;
gboolean drained;
GstFreeverbPrivate *priv;