diff options
author | Andy Wingo <wingo@pobox.com> | 2001-12-22 23:27:31 +0000 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2001-12-22 23:27:31 +0000 |
commit | 185612aae3b8acae2b32e0e6561691a7c640cd0d (patch) | |
tree | 7cd1990c3df5c63f402f3e0bdf6b51b3ed58fc41 /gst/level | |
parent | 87dab192cf5792f847a22e0c3e9afe78553739b5 (diff) |
Initial revision
Original commit message from CVS:
Initial revision
Diffstat (limited to 'gst/level')
-rw-r--r-- | gst/level/Makefile.am | 10 | ||||
-rw-r--r-- | gst/level/README | 11 | ||||
-rw-r--r-- | gst/level/filter.func | 45 | ||||
-rw-r--r-- | gst/level/gstlevel.c | 285 | ||||
-rw-r--r-- | gst/level/gstlevel.h | 69 |
5 files changed, 420 insertions, 0 deletions
diff --git a/gst/level/Makefile.am b/gst/level/Makefile.am new file mode 100644 index 00000000..df87d6c4 --- /dev/null +++ b/gst/level/Makefile.am @@ -0,0 +1,10 @@ +filterdir = $(libdir)/gst + +filter_LTLIBRARIES = libgstlevel.la + +libgstlevel_la_SOURCES = gstlevel.c +libgstlevel_la_CFLAGS = $(GST_CFLAGS) + +noinst_HEADERS = gstlevel.h filter.func + +EXTRA_DIST = README diff --git a/gst/level/README b/gst/level/README new file mode 100644 index 00000000..c7dbf4ca --- /dev/null +++ b/gst/level/README @@ -0,0 +1,11 @@ +level plugin by thomas <thomas@apestaart.org> + +basic level indicator; prints out RMS values averaged over the buffer of +one iteration. Insert this into an audio/raw chain. + +You can plot the level envelope of the track using gnuplot, example : + +tools/gstreamer-launch disksrc location=foo.wav ! parsewav ! level ! \ + fakesink silent=true > foo.level +graph -T gif foo.level > foo.gif +xview dark.gif diff --git a/gst/level/filter.func b/gst/level/filter.func new file mode 100644 index 00000000..ccdaf616 --- /dev/null +++ b/gst/level/filter.func @@ -0,0 +1,45 @@ +{ + guint j; + double squaresum = 0.0; + double RMS = 0.0; + double RMS_dB = 0.0; + static int threshold_dB = -80; + static long int sample = 0; + double timepoint; + + /* + * process data here + * input sample data enters in *in_data as 8 or 16 bit data + * samples for left and right channel are interleaved + */ +/* + for(j = 0; j < num_samples; j++) { + (*out_data)[j] = in_data[j]; + squaresum += in_data[j] * in_data[j]; + } + RMS = sqrt (squaresum / (float) num_samples); + printf ("RMS for this block : %f\n", RMS); + RMS_dB = 20 * log (RMS / 32767); + printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); +*/ + + for(j = 0; j < num_samples; j++) { + (*out_data)[j] = in_data[j]; + squaresum += pow ((double) in_data[j] / 32767.0, 2); + } + RMS = sqrt (squaresum / (float) num_samples); + RMS_dB = 10 * log (RMS); + sample += num_samples; + timepoint = sample / (44100.0 * 2); + + if (RMS_dB > (double) threshold_dB) + { +/* printf ("Reached %d dB at %f sec (%f dB)\n", + threshold_dB, timepoint, RMS_dB); +*/ + threshold_dB += 1; + } +/* printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); */ + printf ("%f %f\n", timepoint, RMS_dB); +} + diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c new file mode 100644 index 00000000..cd839a32 --- /dev/null +++ b/gst/level/gstlevel.c @@ -0,0 +1,285 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gst/gst.h> +#include "gstlevel.h" +#include "math.h" + + +static GstElementDetails level_details = { + "Level", + "Filter/Effect", + "RMS Level indicator for audio/raw", + VERSION, + "Thomas <thomas@apestaart.org>", + "(C) 2001", +}; + + +/* Filter signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0 +}; + +static GstPadTemplate* +level_src_factory (void) +{ + static GstPadTemplate *template = NULL; + + if (!template) { + template = gst_padtemplate_new ( + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + gst_caps_new ( + "test_src", + "audio/raw", + gst_props_new ( + "channels", GST_PROPS_INT_RANGE (1, 2), + NULL)), + NULL); + } + return template; +} + +static GstPadTemplate* +level_sink_factory (void) +{ + static GstPadTemplate *template = NULL; + + if (!template) { + template = gst_padtemplate_new ( + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + gst_caps_new ( + "test_src", + "audio/raw", + gst_props_new ( + "channels", GST_PROPS_INT_RANGE (1, 2), + NULL)), + NULL); + } + return template; +} + +static void gst_level_class_init (GstLevelClass *klass); +static void gst_level_init (GstLevel *filter); + +static void gst_level_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void gst_level_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + +static void gst_level_chain (GstPad *pad, GstBuffer *buf); +static void inline gst_level_fast_16bit_chain (gint16* data, gint16** out_data, + guint numsamples); +static void inline gst_level_fast_8bit_chain (gint8* data, gint8** out_data, + guint numsamples); + +static GstElementClass *parent_class = NULL; +//static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; + +static GstPadNegotiateReturn +level_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data) +{ + GstLevel* filter = GST_LEVEL (gst_pad_get_parent (pad)); + + if (*caps==NULL) + return GST_PAD_NEGOTIATE_FAIL; + + return gst_pad_negotiate_proxy(pad,filter->sinkpad,caps); +} + +static GstPadNegotiateReturn +level_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data) +{ + GstLevel* filter = GST_LEVEL (gst_pad_get_parent (pad)); + + if (*caps==NULL) + return GST_PAD_NEGOTIATE_FAIL; + + return gst_pad_negotiate_proxy(pad,filter->srcpad,caps); +} + +GType +gst_level_get_type(void) { + static GType level_type = 0; + + if (!level_type) { + static const GTypeInfo level_info = { + sizeof(GstLevelClass), NULL, + NULL, + (GClassInitFunc)gst_level_class_init, + NULL, + NULL, + sizeof(GstLevel), + 0, + (GInstanceInitFunc)gst_level_init, + }; + level_type = g_type_register_static(GST_TYPE_ELEMENT, "GstLevel", &level_info, 0); + } + return level_type; +} + +static void +gst_level_class_init (GstLevelClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_level_set_property; + gobject_class->get_property = gst_level_get_property; +} + +static void +gst_level_init (GstLevel *filter) +{ + filter->sinkpad = gst_pad_new_from_template(level_sink_factory (),"sink"); + filter->srcpad = gst_pad_new_from_template(level_src_factory (),"src"); + + gst_pad_set_negotiate_function(filter->sinkpad,level_negotiate_sink); + gst_pad_set_negotiate_function(filter->srcpad,level_negotiate_src); + + gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad); + gst_pad_set_chain_function(filter->sinkpad,gst_level_chain); + filter->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad); +} + +static void +gst_level_chain (GstPad *pad,GstBuffer *buf) +{ + GstLevel *filter; + gint16 *in_data; + gint16 *out_data; + GstBuffer* outbuf; + gint width; + + GstCaps *caps; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + filter = GST_LEVEL(GST_OBJECT_PARENT (pad)); + g_return_if_fail(filter != NULL); + g_return_if_fail(GST_IS_LEVEL(filter)); + + caps = NULL; + caps = GST_PAD_CAPS(pad); + if (caps == NULL) + { + // FIXME : Please change this to a better warning method ! + printf ("WARNING : chain : Could not get caps of pad !\n"); + } + + width = gst_caps_get_int(caps, "width"); + + in_data = (gint16 *)GST_BUFFER_DATA(buf); + outbuf=gst_buffer_new(); + GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf)/2); + GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf); + + out_data = (gint16*)GST_BUFFER_DATA(outbuf); + + switch (width) { + case 16: + gst_level_fast_16bit_chain(in_data,&out_data,GST_BUFFER_SIZE(buf)/2); + break; + case 8: + gst_level_fast_8bit_chain((gint8*)in_data,(gint8**)&out_data,GST_BUFFER_SIZE(buf)); + break; + } + gst_buffer_unref(buf); + gst_pad_push(filter->srcpad,outbuf); +} + +static void inline +gst_level_fast_16bit_chain(gint16* in_data, gint16** out_data, + guint num_samples) +#include "filter.func" + +static void inline +gst_level_fast_8bit_chain(gint8* in_data, gint8** out_data, + guint num_samples) +#include "filter.func" + +static void +gst_level_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstLevel *filter; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_LEVEL(object)); + filter = GST_LEVEL(object); + + switch (prop_id) { + default: + break; + } +} + +static void +gst_level_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstLevel *filter; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_LEVEL(object)); + filter = GST_LEVEL(object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + factory = gst_elementfactory_new("level",GST_TYPE_LEVEL, + &level_details); + g_return_val_if_fail(factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate (factory, level_src_factory ()); + gst_elementfactory_add_padtemplate (factory, level_sink_factory ()); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "level", + plugin_init +}; diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h new file mode 100644 index 00000000..f9dade0a --- /dev/null +++ b/gst/level/gstlevel.h @@ -0,0 +1,69 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_LEVEL_H__ +#define __GST_LEVEL_H__ + + +#include <config.h> +#include <gst/gst.h> +// #include <gst/meta/audioraw.h> + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_LEVEL \ + (gst_level_get_type()) +#define GST_LEVEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LEVEL,GstLevel)) +#define GST_LEVEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstLevel)) +#define GST_IS_LEVEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LEVEL)) +#define GST_IS_LEVEL_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LEVEL)) + +typedef struct _GstLevel GstLevel; +typedef struct _GstLevelClass GstLevelClass; + +struct _GstLevel { + GstElement element; + + GstPad *sinkpad,*srcpad; + + //MetaAudioRaw meta; + +}; + +struct _GstLevelClass { + GstElementClass parent_class; +}; + +GType gst_level_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_STEREO_H__ */ |