From: Thomas V. S. <tho...@us...> - 2002-08-30 13:37:44
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Fri Aug 30 2002 06:37:43 PDT Log message: cleanups and clarifications Modified files: gst/level : filter.func gstlevel.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/filter.func.diff?r1=1.1.1.1&r2=1.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.8&r2=1.9 ====Begin Diffs==== Index: filter.func =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/filter.func,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- filter.func 22 Dec 2001 23:23:39 -0000 1.1.1.1 +++ filter.func 30 Aug 2002 13:37:31 -0000 1.2 @@ -40,6 +40,6 @@ threshold_dB += 1; } /* printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); */ - printf ("%f %f\n", timepoint, RMS_dB); + printf ("%f s %f dB\n", timepoint, RMS_dB); } Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- gstlevel.c 27 Aug 2002 17:45:07 -0000 1.8 +++ gstlevel.c 30 Aug 2002 13:37:31 -0000 1.9 @@ -172,41 +172,46 @@ 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); + 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); + out_data = (gint16 *) GST_BUFFER_DATA (outbuf); + g_print ("%s: ", gst_element_get_name (GST_ELEMENT (filter))); switch (width) { case 16: - gst_level_fast_16bit_chain(in_data,&out_data,GST_BUFFER_SIZE(buf)/2); + 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)); + 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); + 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) +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) +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) +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); + g_return_if_fail (GST_IS_LEVEL (object)); + filter = GST_LEVEL (object); switch (prop_id) { default: @@ -215,13 +220,14 @@ } static void -gst_level_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +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); + g_return_if_fail (GST_IS_LEVEL (object)); + filter = GST_LEVEL (object); switch (prop_id) { default: @@ -264,9 +270,9 @@ { GstElementFactory *factory; - factory = gst_element_factory_new("level",GST_TYPE_LEVEL, - &level_details); - g_return_val_if_fail(factory != NULL, FALSE); + factory = gst_element_factory_new ("level", GST_TYPE_LEVEL, + &level_details); + g_return_val_if_fail (factory != NULL, FALSE); gst_element_factory_add_pad_template (factory, level_src_factory ()); gst_element_factory_add_pad_template (factory, level_sink_factory ()); |
From: Thomas V. S. <tho...@us...> - 2003-09-21 12:22:30
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 21 2003 05:22:01 PDT Log message: reworked level plugin. It now does RMS, peak, and decay peak signaling per interleaved channel. Modified files: gst/level : Makefile.am README filter.func gstlevel.c gstlevel.h Added files: gst/level : gstlevel-marshal.list Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.7&r2=1.8 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/README.diff?r1=1.1.1.1&r2=1.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/filter.func.diff?r1=1.3&r2=1.4 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list?rev=1.1&content-type=text/vnd.viewcvs-markup http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.16&r2=1.17 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.h.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Makefile.am 9 Aug 2003 23:46:25 -0000 1.7 +++ Makefile.am 21 Sep 2003 12:21:48 -0000 1.8 @@ -1,11 +1,33 @@ plugin_LTLIBRARIES = libgstlevel.la -libgstlevel_la_SOURCES = gstlevel.c +libgstlevel_la_SOURCES = gstlevel.c gstlevel-marshal.c libgstlevel_la_CFLAGS = $(GST_CFLAGS) libgstlevel_la_LIBADD = libgstlevel_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstlevel.h filter.func + +EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list + +BUILT_SOURCES = \ + gstlevel-marshal.c \ + gstlevel-marshal.h + +gstlevel-marshal.h: gstlevel-marshal.list + glib-genmarshal --header --prefix=gstlevel_cclosure_marshal $(srcdir)/gstlevel-marshal.list > gstlevel-marshal.h.tmp + mv gstlevel-marshal.h.tmp gstlevel-marshal.h + +gstlevel-marshal.c: gstlevel-marshal.list + echo "#include \"glib.h\"" > gstlevel-marshal.c.tmp + echo "#include \"glib-object.h\"" >> gstlevel-marshal.c.tmp + echo "#include \"gstlevel-marshal.h\"" >> gstlevel-marshal.c.tmp + glib-genmarshal --body --prefix=gstlevel_cclosure_marshal $(srcdir)/gstlevel-marshal.list >> gstlevel-marshal.c.tmp + mv gstlevel-marshal.c.tmp gstlevel-marshal.c + +# Don't want the generated marshal files in the dist +dist-hook: + rm -f $(distdir)/gstlevel-marshal.c + rm -f $(distdir)/gstlevel-marshal.h EXTRA_DIST = README Index: README =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/README,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- README 22 Dec 2001 23:23:39 -0000 1.1.1.1 +++ README 21 Sep 2003 12:21:49 -0000 1.2 @@ -1,11 +1,21 @@ level plugin by thomas <th...@ap...> -basic level indicator; prints out RMS values averaged over the buffer of -one iteration. Insert this into an audio/raw chain. +this plugin signals: + - channel + - RMS level + - peak level + - decaying peak level +over the given interval. + +This is useful for a VU meter display and for plotting out the signal graph. +The VU meter can either display RMS, or display immediate peak level and +have the falloff decaying peak level displayed as a line. + +The interval for signal emission, ttl of decay peak, and falloff of decay peak +can all be set. + +The element only takes unsigned data in; it could be extended to signed as +well, if separate fast chain functions are made that displaces the incoming +data to its midpoint (ie, 0,65535 should be mapped to -32768, 32767) -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 Index: filter.func =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/filter.func,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- filter.func 30 Jun 2003 06:54:18 -0000 1.3 +++ filter.func 21 Sep 2003 12:21:49 -0000 1.4 @@ -1,45 +1,34 @@ +/* process one (interleaved) channel of incoming samples + * calculate square sum of samples + * normalize and return normalized Cumulative Square + * caller must assure num is a multiple of channels + * this filter only accepts signed audio data, so mid level is always 0 + */ { - 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; + register int j; + double squaresum = 0.0; /* square sum of the integer samples */ + register double square = 0.0; /* Square */ + register double PSS = 0.0; /* Peak Square Sample */ + + *CS = 0.0; /* Cumulative Square for this block */ + + gdouble normalizer = (double) (1 << resolution); /* * process data here * input sample data enters in *in_data as 8 or 16 bit data * samples for left and right channel are interleaved + * returns the Mean Square of the samples as a double between 0 and 1 */ -/* - 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) + for (j = 0; j < num; j += channels) { -/* printf ("Reached %d dB at %f sec (%f dB)\n", - threshold_dB, timepoint, RMS_dB); -*/ - threshold_dB += 1; + square = (double) (in[j] * in[j]); + if (square > PSS) PSS = square; + squaresum += square; } -/* printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); */ - printf ("%f s %f dB\n", timepoint, RMS_dB); + *peak = PSS / ((double) normalizer * (double) normalizer); + + /* return normalized cumulative square */ + *CS = squaresum / ((double) normalizer * (double) normalizer); } - --- NEW FILE: gstlevel-marshal.list --- VOID:INT,DOUBLE,DOUBLE,DOUBLE Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- gstlevel.c 6 Jul 2003 20:49:39 -0000 1.16 +++ gstlevel.c 21 Sep 2003 12:21:49 -0000 1.17 @@ -1,6 +1,10 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * + * gstlevel.c: signals RMS, peak and decaying peak levels + * Copyright (C) 2000,2001,2002,2003 + * Thomas Vander Stichele <thomas at apestaart dot org> + * * 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 @@ -17,34 +21,35 @@ * Boston, MA 02111-1307, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif #include <gst/gst.h> #include "gstlevel.h" #include "math.h" -#include <gst/audio/audio.h> /* elementfactory information */ static GstElementDetails level_details = { "Level", "Filter/Audio/Analysis", "LGPL", - "RMS Level indicator for audio/raw", + "RMS/Peak/Decaying Peak Level signaller for audio/raw", VERSION, "Thomas <th...@ap...>", - "(C) 2001", + "(C) 2001, 2003, 2003", }; /* Filter signals and args */ enum { /* FILL ME */ + SIGNAL_LEVEL, LAST_SIGNAL }; enum { - ARG_0 + ARG_0, + ARG_SIGNAL_LEVEL, + ARG_SIGNAL_INTERVAL, + ARG_PEAK_TTL, + ARG_PEAK_FALLOFF }; static GstPadTemplate* @@ -59,11 +64,12 @@ GST_PAD_ALWAYS, gst_caps_new ( "test_src", - "audio/x-raw-int", - GST_AUDIO_INT_PAD_TEMPLATE_PROPS - ), - NULL - ); + "audio/raw", + gst_props_new ( + "channels", GST_PROPS_INT_RANGE (1, 2), + "signed", GST_PROPS_BOOLEAN (TRUE), + NULL)), + NULL); } return template; } @@ -80,11 +86,12 @@ GST_PAD_ALWAYS, gst_caps_new ( "test_src", - "audio/x-raw-int", - GST_AUDIO_INT_PAD_TEMPLATE_PROPS - ), - NULL - ); + "audio/raw", + gst_props_new ( + "channels", GST_PROPS_INT_RANGE (1, 2), + "signed", GST_PROPS_BOOLEAN (TRUE), + NULL)), + NULL); } return template; } @@ -96,13 +103,9 @@ 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 guint gst_filter_signals[LAST_SIGNAL] = { 0 }; GType gst_level_get_type (void) @@ -129,6 +132,8 @@ { GstLevel *filter; GstPad *otherpad; + GstPadLinkReturn res; + int i; filter = GST_LEVEL (gst_pad_get_parent (pad)); g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED); @@ -137,73 +142,172 @@ if (GST_CAPS_IS_FIXED (caps)) { - /*if ( !volume_parse_caps (filter, caps) || */ - return gst_pad_try_set_caps (otherpad, gst_caps_ref (caps)); + /* yep, got them */ + res = gst_pad_try_set_caps (otherpad, caps); + /* if ok, set filter */ + if (res == GST_PAD_LINK_OK) + { + filter->num_samples = 0; + /* FIXME: error handling */ + if (! gst_caps_get_int (caps, "rate", &(filter->rate))) + g_warning ("WARNING: level: Could not get rate from caps\n"); + if (!gst_caps_get_int (caps, "width", &(filter->width))) + g_warning ("WARNING: level: Could not get width from caps\n"); + if (!gst_caps_get_int (caps, "channels", &(filter->channels))) + g_warning ("WARNING: level: Could not get number of channels from caps\n"); + + /* allocate channel variable arrays */ + if (filter->CS) g_free (filter->CS); + if (filter->peak) g_free (filter->peak); + if (filter->last_peak) g_free (filter->last_peak); + if (filter->decay_peak) g_free (filter->decay_peak); + if (filter->decay_peak_age) g_free (filter->decay_peak_age); + if (filter->MS) g_free (filter->MS); + if (filter->RMS_dB) g_free (filter->RMS_dB); + filter->CS = g_new (double, filter->channels); + filter->peak = g_new (double, filter->channels); + filter->last_peak = g_new (double, filter->channels); + filter->decay_peak = g_new (double, filter->channels); + filter->decay_peak_age = g_new (double, filter->channels); + filter->MS = g_new (double, filter->channels); + filter->RMS_dB = g_new (double, filter->channels); + for (i = 0; i < filter->channels; ++i) + { + filter->CS[i] = filter->peak[i] = filter->last_peak[i] = + filter->decay_peak[i] = filter->decay_peak_age[i] = + filter->MS[i] = filter->RMS_dB[i] = 0.0; + } + } + return res; } return GST_PAD_LINK_DELAYED; } +static void inline +gst_level_fast_16bit_chain (gint16* in, guint num, gint channels, + gint resolution, double *CS, double *peak) +#include "filter.func" + +static void inline +gst_level_fast_8bit_chain (gint8* in, guint num, gint channels, + gint resolution, double *CS, double *peak) +#include "filter.func" + static void gst_level_chain (GstPad *pad, GstBuffer *buf) { GstLevel *filter; gint16 *in_data; - gint16 *out_data; - GstBuffer* outbuf; - gint width; - GstCaps *caps; + double CS = 0.0; + gint num_samples = 0; + gint i; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (buf != NULL); + + g_print ("\nDEBUG: chain start\n"); 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) + for (i = 0; i < filter->channels; ++i) + filter->CS[i] = filter->peak[i] = filter->MS[i] = filter->RMS_dB[i] = 0.0; + + in_data = (gint16 *) GST_BUFFER_DATA(buf); + + num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); + if (num_samples % filter->channels != 0) + g_warning ("WARNING: level: programming error, data not properly interleaved"); + + for (i = 0; i < filter->channels; ++i) { - /* FIXME : Please change this to a better warning method ! */ - g_error ("WARNING: level: Could not get pad caps - caps nego failed !\n"); + switch (filter->width) + { + case 16: + gst_level_fast_16bit_chain (in_data + i, num_samples, + filter->channels, filter->width - 1, + &CS, &filter->peak[i]); + break; + case 8: + gst_level_fast_8bit_chain (((gint8 *) in_data) + i, num_samples, + filter->channels, filter->width - 1, + &CS, &filter->peak[i]); + break; + } + g_print ("DEBUG: CS %f, peak %f\n", CS, filter->peak[i]); + filter->CS[i] += CS; + } + gst_pad_push (filter->srcpad, buf); - gst_caps_get_int (caps, "width", &width); + filter->num_samples += num_samples; - 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); + for (i = 0; i < filter->channels; ++i) + { + filter->decay_peak_age[i] += num_samples; + g_print ("filter peak info [%d]: peak %f, age %f\n", i, + filter->last_peak[i], filter->decay_peak_age[i]); + /* update running peak */ + if (filter->peak[i] > filter->last_peak[i]) + filter->last_peak[i] = filter->peak[i]; - out_data = (gint16 *) GST_BUFFER_DATA (outbuf); + /* update decay peak */ + if (filter->peak[i] >= filter->decay_peak[i]) + { + g_print ("new peak, %f\n", filter->peak[i]); + filter->decay_peak[i] = filter->peak[i]; + filter->decay_peak_age[i] = 0; + } + else + { + /* make decay peak fall off if too old */ + if (filter->decay_peak_age[i] > filter->rate * filter->decay_peak_ttl) + { + double falloff_dB; + double falloff; + double length; /* length of buffer in seconds */ + + + length = (double) num_samples / (filter->channels * filter->rate); + falloff_dB = filter->decay_peak_falloff * length; + falloff = pow (10, falloff_dB / -20.0); + + g_print ("falloff: length %f, dB falloff %f, falloff factor %e\n", + length, falloff_dB, falloff); + filter->decay_peak[i] *= falloff; + g_print ("peak is %f samples old, decayed with factor %e to %f\n", + filter->decay_peak_age[i], falloff, filter->decay_peak[i]); + } + } + } + + /* do we need to emit ? */ - g_print ("%s: ", gst_element_get_name (GST_ELEMENT (filter))); - 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; + if (filter->num_samples >= filter->interval * (gdouble) filter->rate) + { + if (filter->signal) + { + gdouble RMS, peak; + for (i = 0; i < filter->channels; ++i) + { + RMS = sqrt (filter->CS[i] / (filter->num_samples / filter->channels)); + peak = filter->last_peak[i]; + + g_signal_emit (G_OBJECT (filter), gst_filter_signals[SIGNAL_LEVEL], 0, + i, 20 * log10 (RMS), 20 * log10 (filter->last_peak[i]), + 20 * log10 (filter->decay_peak[i])); + /* we emitted, so reset cumulative and normal peak */ + filter->CS[i] = 0.0; + filter->last_peak[i] = 0.0; + } + } + filter->num_samples = 0; } - 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, @@ -216,6 +320,18 @@ filter = GST_LEVEL (object); switch (prop_id) { + case ARG_SIGNAL_LEVEL: + filter->signal = g_value_get_boolean (value); + break; + case ARG_SIGNAL_INTERVAL: + filter->interval = g_value_get_double (value); + break; + case ARG_PEAK_TTL: + filter->decay_peak_ttl = g_value_get_double (value); + break; + case ARG_PEAK_FALLOFF: + filter->decay_peak_falloff = g_value_get_double (value); + break; default: break; } @@ -232,7 +348,19 @@ filter = GST_LEVEL (object); switch (prop_id) { - default: + case ARG_SIGNAL_LEVEL: + g_value_set_boolean (value, filter->signal); + break; + case ARG_SIGNAL_INTERVAL: + g_value_set_double (value, filter->interval); + break; + case ARG_PEAK_TTL: + g_value_set_double (value, filter->decay_peak_ttl); + break; + case ARG_PEAK_FALLOFF: + g_value_set_double (value, filter->decay_peak_falloff); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } @@ -248,9 +376,32 @@ gstelement_class = (GstElementClass*) klass; parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_LEVEL, + g_param_spec_boolean ("signal", "Signal", + "Emit level signals for each interval", + TRUE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_INTERVAL, + g_param_spec_double ("interval", "Interval", + "Interval between emissions (in seconds)", + 0.01, 100.0, 0.1, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PEAK_TTL, + g_param_spec_double ("peak_ttl", "Peak TTL", + "Time To Live of decay peak before it falls back", + 0, 100.0, 0.3, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PEAK_FALLOFF, + g_param_spec_double ("peak_falloff", "Peak Falloff", + "Decay rate of decay peak after TTL (in dB/sec)", + 0.0, G_MAXDOUBLE, 10.0, G_PARAM_READWRITE)); gobject_class->set_property = gst_level_set_property; gobject_class->get_property = gst_level_get_property; + + gst_filter_signals[SIGNAL_LEVEL] = + g_signal_new ("level", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstLevelClass, level), NULL, NULL, + gstlevel_cclosure_marshal_VOID__INT_DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, 4, + G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); } static void @@ -265,6 +416,19 @@ 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); + + filter->CS = NULL; + filter->peak = NULL; + filter->MS = NULL; + filter->RMS_dB = NULL; + + filter->rate = 0; + filter->width = 0; + filter->channels = 0; + + filter->interval = 0.1; + filter->decay_peak_ttl = 0.4; + filter->decay_peak_falloff = 10.0; /* dB falloff (/sec) */ } static gboolean Index: gstlevel.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- gstlevel.h 20 Mar 2002 21:44:51 -0000 1.3 +++ gstlevel.h 21 Sep 2003 12:21:49 -0000 1.4 @@ -1,6 +1,10 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * + * gstlevel.c: signals RMS, peak and decaying peak levels + * Copyright (C) 2000,2001,2002,2003 + * Thomas Vander Stichele <thomas at apestaart dot org> + * * 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 @@ -24,8 +28,8 @@ #include <config.h> #include <gst/gst.h> -/* #include <gst/meta/audioraw.h> */ +#include "gstlevel-marshal.h" #ifdef __cplusplus extern "C" { @@ -49,14 +53,32 @@ struct _GstLevel { GstElement element; - GstPad *sinkpad,*srcpad; + GstPad *sinkpad, *srcpad; + gboolean signal; /* whether or not to emit signals */ + gdouble interval; /* how many seconds between emits */ - /*MetaAudioRaw meta; */ + gint rate; /* caps variables */ + gint width; + gint channels; + gdouble decay_peak_ttl; /* time to live for peak in seconds */ + gdouble decay_peak_falloff; /* falloff in dB/sec */ + gdouble num_samples; /* cumulative sample count */ + + /* per-channel arrays for intermediate values */ + gdouble *CS; /* normalized Cumulative Square */ + gdouble *peak; /* normalized Peak value over buffer */ + gdouble *last_peak; /* last normalized Peak value over interval */ + gdouble *decay_peak; /* running decaying normalized Peak */ + gdouble *MS; /* normalized Mean Square of buffer */ + gdouble *RMS_dB; /* RMS in dB to emit */ + gdouble *decay_peak_age; /* age of last peak */ }; struct _GstLevelClass { GstElementClass parent_class; + void (*level) (GstElement *element, gint channel, + gdouble RMS_dB, gdouble peak_dB, gdouble decay_peak_dB); }; GType gst_level_get_type(void); |
From: Thomas V. S. <tho...@us...> - 2003-09-21 12:53:09
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 21 2003 05:53:08 PDT Log message: remove debugging prints Modified files: gst/level : Makefile.am gstlevel.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.8&r2=1.9 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.17&r2=1.18 ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- Makefile.am 21 Sep 2003 12:21:48 -0000 1.8 +++ Makefile.am 21 Sep 2003 12:52:55 -0000 1.9 @@ -8,6 +8,11 @@ noinst_HEADERS = gstlevel.h filter.func +noinst_PROGRAMS = demo +demo_SOURCES = demo.c +demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) + EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list BUILT_SOURCES = \ Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- gstlevel.c 21 Sep 2003 12:21:49 -0000 1.17 +++ gstlevel.c 21 Sep 2003 12:52:55 -0000 1.18 @@ -208,7 +208,6 @@ g_return_if_fail (buf != NULL); - g_print ("\nDEBUG: chain start\n"); filter = GST_LEVEL (GST_OBJECT_PARENT (pad)); g_return_if_fail (filter != NULL); g_return_if_fail (GST_IS_LEVEL (filter)); @@ -237,7 +236,7 @@ &CS, &filter->peak[i]); break; } - g_print ("DEBUG: CS %f, peak %f\n", CS, filter->peak[i]); + /* g_print ("DEBUG: CS %f, peak %f\n", CS, filter->peak[i]); */ filter->CS[i] += CS; } @@ -248,8 +247,8 @@ for (i = 0; i < filter->channels; ++i) { filter->decay_peak_age[i] += num_samples; - g_print ("filter peak info [%d]: peak %f, age %f\n", i, - filter->last_peak[i], filter->decay_peak_age[i]); + /* g_print ("filter peak info [%d]: peak %f, age %f\n", i, + filter->last_peak[i], filter->decay_peak_age[i]); */ /* update running peak */ if (filter->peak[i] > filter->last_peak[i]) filter->last_peak[i] = filter->peak[i]; @@ -257,7 +256,7 @@ /* update decay peak */ if (filter->peak[i] >= filter->decay_peak[i]) { - g_print ("new peak, %f\n", filter->peak[i]); + /* g_print ("new peak, %f\n", filter->peak[i]); */ filter->decay_peak[i] = filter->peak[i]; filter->decay_peak_age[i] = 0; } @@ -275,11 +274,11 @@ falloff_dB = filter->decay_peak_falloff * length; falloff = pow (10, falloff_dB / -20.0); - g_print ("falloff: length %f, dB falloff %f, falloff factor %e\n", - length, falloff_dB, falloff); + /* g_print ("falloff: length %f, dB falloff %f, falloff factor %e\n", + length, falloff_dB, falloff); */ filter->decay_peak[i] *= falloff; - g_print ("peak is %f samples old, decayed with factor %e to %f\n", - filter->decay_peak_age[i], falloff, filter->decay_peak[i]); + /* g_print ("peak is %f samples old, decayed with factor %e to %f\n", + filter->decay_peak_age[i], falloff, filter->decay_peak[i]); */ } } } |
From: Thomas V. S. <tho...@us...> - 2003-09-21 13:08:43
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 21 2003 06:08:41 PDT Log message: fix caps Modified files: gst/level : gstlevel.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.18&r2=1.19 ====Begin Diffs==== Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- gstlevel.c 21 Sep 2003 12:52:55 -0000 1.18 +++ gstlevel.c 21 Sep 2003 13:08:29 -0000 1.19 @@ -36,6 +36,49 @@ "(C) 2001, 2003, 2003", }; +/* pad templates */ + +GST_PAD_TEMPLATE_FACTORY (sink_template_factory, + "level_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "level_sink", + "audio/x-raw-int", + "signed", GST_PROPS_BOOLEAN (TRUE), + "width", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "depth", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "rate", GST_PROPS_INT_RANGE (1, G_MAXINT), + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +) + +GST_PAD_TEMPLATE_FACTORY (src_template_factory, + "level_src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "level_src", + "audio/x-raw-int", + "signed", GST_PROPS_BOOLEAN (TRUE), + "width", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "depth", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "rate", GST_PROPS_INT_RANGE (1, G_MAXINT), + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +) /* Filter signals and args */ enum { @@ -52,50 +95,6 @@ ARG_PEAK_FALLOFF }; -static GstPadTemplate* -level_src_factory (void) -{ - static GstPadTemplate *template = NULL; - - if (!template) { - template = gst_pad_template_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), - "signed", GST_PROPS_BOOLEAN (TRUE), - NULL)), - NULL); - } - return template; -} - -static GstPadTemplate* -level_sink_factory (void) -{ - static GstPadTemplate *template = NULL; - - if (!template) { - template = gst_pad_template_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), - "signed", GST_PROPS_BOOLEAN (TRUE), - NULL)), - NULL); - } - return template; -} - static void gst_level_class_init (GstLevelClass *klass); static void gst_level_init (GstLevel *filter); @@ -406,9 +405,9 @@ static void gst_level_init (GstLevel *filter) { - filter->sinkpad = gst_pad_new_from_template (level_sink_factory (), "sink"); + filter->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_template_factory), "sink"); gst_pad_set_link_function (filter->sinkpad, gst_level_connect); - filter->srcpad = gst_pad_new_from_template (level_src_factory (), "src"); + filter->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_template_factory), "src"); gst_pad_set_link_function (filter->srcpad, gst_level_connect); gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); @@ -439,8 +438,8 @@ &level_details); g_return_val_if_fail (factory != NULL, FALSE); - gst_element_factory_add_pad_template (factory, level_src_factory ()); - gst_element_factory_add_pad_template (factory, level_sink_factory ()); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template_factory)); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template_factory)); gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); |
From: Thomas V. S. <tho...@us...> - 2003-09-21 13:24:27
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 21 2003 06:24:25 PDT Log message: build demo app Modified files: gst/level : Makefile.am Added files: gst/level : demo.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.9&r2=1.10 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/demo.c?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- Makefile.am 21 Sep 2003 12:52:55 -0000 1.9 +++ Makefile.am 21 Sep 2003 13:24:13 -0000 1.10 @@ -8,10 +8,12 @@ noinst_HEADERS = gstlevel.h filter.func +if HAVE_GTK noinst_PROGRAMS = demo demo_SOURCES = demo.c demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) +endif EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list --- NEW FILE: demo.c --- /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * * demo.c: sample application to display VU meter-like output of level * Copyright (C) 2003 * Thomas Vander Stichele <thomas at apestaart dot org> * * 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 <gtk/gtk.h> /* global array for the scale widgets, we'll assume stereo */ GtkWidget *scale[2][3]; static void level_callback (GstElement *element, gint channel, gdouble rms, gdouble peak, gdouble decay) { gtk_range_set_value (GTK_RANGE (scale[channel][0]), rms); gtk_range_set_value (GTK_RANGE (scale[channel][1]), peak); gtk_range_set_value (GTK_RANGE (scale[channel][2]), decay); } static gboolean idler (gpointer data) { GstElement *pipeline = GST_ELEMENT (data); g_print ("+"); return gst_bin_iterate (GST_BIN (pipeline)); } static void setup_gui () { GtkWidget *window; GtkWidget *vbox; int c; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "destroy", gtk_main_quit, NULL); vbox = gtk_vbox_new (TRUE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); for (c = 0; c < 2; ++c) { GtkWidget *label, *hbox; /* RMS */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("RMS"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][0] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][0], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][0]); gtk_container_add (GTK_CONTAINER (vbox), hbox); /* peak */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("peak"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][1] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][1], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][1]); gtk_container_add (GTK_CONTAINER (vbox), hbox); /* decay */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("decaying peek"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][2] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][2], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][2]); gtk_container_add (GTK_CONTAINER (vbox), hbox); } gtk_widget_show_all (GTK_WIDGET (window)); } int main (int argc, char *argv[]) { GstElement *pipeline = NULL; GError *error = NULL; GstElement *level; gst_init (&argc, &argv); gtk_init (&argc, &argv); pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error); if (error) { g_print ("pipeline could not be constructed: %s\n", error->message); g_print ("Please give a complete pipeline with a 'level' element.\n"); g_print ("Example: sinesrc ! level ! osssink\n"); g_error_free (error); return 1; } level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); if (level == NULL) { g_print ("Please give a pipeline with a 'level' element in it\n"); return 1; } g_object_set (level, "signal", TRUE, NULL); g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); /* setup GUI */ setup_gui (); /* connect level signal */ /* go to main loop */ gst_element_set_state (pipeline, GST_STATE_PLAYING); g_idle_add (idler, pipeline); gtk_main (); return 0; } |
From: Thomas V. S. <tho...@us...> - 2003-09-26 18:47:20
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Fri Sep 26 2003 09:45:17 PDT Log message: added second example with plotting fixed some aesthetics Modified files: gst/level : Makefile.am README demo.c gstlevel-marshal.list gstlevel.c gstlevel.h Added files: gst/level : plot.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.10&r2=1.11 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/README.diff?r1=1.2&r2=1.3 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/demo.c.diff?r1=1.1&r2=1.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list.diff?r1=1.1&r2=1.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.19&r2=1.20 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.h.diff?r1=1.4&r2=1.5 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/plot.c?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- Makefile.am 21 Sep 2003 13:24:13 -0000 1.10 +++ Makefile.am 26 Sep 2003 16:45:04 -0000 1.11 @@ -9,10 +9,13 @@ noinst_HEADERS = gstlevel.h filter.func if HAVE_GTK -noinst_PROGRAMS = demo +noinst_PROGRAMS = demo plot demo_SOURCES = demo.c demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) +plot_SOURCES = plot.c +plot_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) endif EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list Index: README =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/README,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- README 21 Sep 2003 12:21:49 -0000 1.2 +++ README 26 Sep 2003 16:45:04 -0000 1.3 @@ -1,6 +1,7 @@ level plugin by thomas <th...@ap...> this plugin signals: + - running time since last EOS/start - channel - RMS level - peak level @@ -17,5 +18,22 @@ The element only takes unsigned data in; it could be extended to signed as well, if separate fast chain functions are made that displaces the incoming data to its midpoint (ie, 0,65535 should be mapped to -32768, 32767) + +There are two demo apps, apps and plot. apps will create some GTK sliders +to display the volume. plot will output data readable by gnuplot. + +Here is a sample plot script to plot output of the plot command that was +stored to plot.dat + +set xlabel "Seconds" +set ylabel "dB" +set yrange [-60:0] +plot 'plot.dat' using 1:2 title 'L RMS' with lines, \ + 'plot.dat' using 1:3 title 'L peak' with lines, \ + 'plot.dat' using 1:4 title 'L decay' with lines + +plot 'plot.dat' using 1:5 title 'R RMS' with lines, \ + 'plot.dat' using 1:6 title 'R peak' with lines, \ + 'plot.dat' using 1:7 title 'R decay' with lines Index: demo.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/demo.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- demo.c 21 Sep 2003 13:24:13 -0000 1.1 +++ demo.c 26 Sep 2003 16:45:04 -0000 1.2 @@ -28,7 +28,7 @@ GtkWidget *scale[2][3]; static void -level_callback (GstElement *element, gint channel, +level_callback (GstElement *element, gdouble time, gint channel, gdouble rms, gdouble peak, gdouble decay) { gtk_range_set_value (GTK_RANGE (scale[channel][0]), rms); @@ -41,7 +41,10 @@ { GstElement *pipeline = GST_ELEMENT (data); g_print ("+"); - return gst_bin_iterate (GST_BIN (pipeline)); + if (gst_bin_iterate (GST_BIN (pipeline))) + return TRUE; + gtk_main_quit (); + return FALSE; } static void Index: gstlevel-marshal.list =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- gstlevel-marshal.list 21 Sep 2003 12:21:49 -0000 1.1 +++ gstlevel-marshal.list 26 Sep 2003 16:45:04 -0000 1.2 @@ -1 +1 @@ -VOID:INT,DOUBLE,DOUBLE,DOUBLE +VOID:DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- gstlevel.c 21 Sep 2003 13:08:29 -0000 1.19 +++ gstlevel.c 26 Sep 2003 16:45:04 -0000 1.20 @@ -214,7 +214,7 @@ for (i = 0; i < filter->channels; ++i) filter->CS[i] = filter->peak[i] = filter->MS[i] = filter->RMS_dB[i] = 0.0; - in_data = (gint16 *) GST_BUFFER_DATA(buf); + in_data = (gint16 *) GST_BUFFER_DATA (buf); num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); if (num_samples % filter->channels != 0) @@ -288,14 +288,18 @@ { if (filter->signal) { - gdouble RMS, peak; + gdouble RMS, peak, endtime; for (i = 0; i < filter->channels; ++i) { RMS = sqrt (filter->CS[i] / (filter->num_samples / filter->channels)); peak = filter->last_peak[i]; + num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); + endtime = (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND + + (double) num_samples / (double) filter->rate; g_signal_emit (G_OBJECT (filter), gst_filter_signals[SIGNAL_LEVEL], 0, - i, 20 * log10 (RMS), 20 * log10 (filter->last_peak[i]), + endtime, i, + 20 * log10 (RMS), 20 * log10 (filter->last_peak[i]), 20 * log10 (filter->decay_peak[i])); /* we emitted, so reset cumulative and normal peak */ filter->CS[i] = 0.0; @@ -397,9 +401,10 @@ gst_filter_signals[SIGNAL_LEVEL] = g_signal_new ("level", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstLevelClass, level), NULL, NULL, - gstlevel_cclosure_marshal_VOID__INT_DOUBLE_DOUBLE_DOUBLE, - G_TYPE_NONE, 4, - G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); + gstlevel_cclosure_marshal_VOID__DOUBLE_INT_DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, 5, + G_TYPE_DOUBLE, G_TYPE_INT, + G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); } static void Index: gstlevel.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- gstlevel.h 21 Sep 2003 12:21:49 -0000 1.4 +++ gstlevel.h 26 Sep 2003 16:45:04 -0000 1.5 @@ -77,7 +77,7 @@ struct _GstLevelClass { GstElementClass parent_class; - void (*level) (GstElement *element, gint channel, + void (*level) (GstElement *element, gdouble time, gint channel, gdouble RMS_dB, gdouble peak_dB, gdouble decay_peak_dB); }; --- NEW FILE: plot.c --- /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * * plot.c: output data points to be graphed with gnuplot * Copyright (C) 2003 * Thomas Vander Stichele <thomas at apestaart dot org> * * 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 <gtk/gtk.h> gboolean got_channel[2] = { FALSE, FALSE}; /* to see if we got the signal for this one yet */ gint channels = 0 ; /* guess at how many channels there are */ gdouble last_time = 0.0; /* time of last signal */ gdouble values[2][3]; /* array of levels from which to print */ static void level_callback (GstElement *element, gdouble time, gint channel, gdouble rms, gdouble peak, gdouble decay) { int i = 0, j = 0; gboolean got_all = FALSE; if (channel + 1> channels) channels = channel + 1; /* reset got_channel if this is a new time point */ if (time > last_time) { for (i = 0; i < channels; ++i) got_channel[i] = FALSE; last_time = time; } /* store values */ got_channel[channel] = TRUE; values[channel][0] = rms; values[channel][1] = peak; values[channel][2] = decay; /* check if we have all channels, and output if we do */ /* FIXME: this fails on the first, no ? */ got_all = TRUE; for (i = 0; i < channels; ++i) if (!got_channel[i]) got_all = FALSE; if (got_all) { g_print ("%f ", time); for (i = 0; i < channels; ++i) for (j = 0; j < 3; ++j) g_print ("%f ", values[i][j]); g_print ("\n"); } } static gboolean idler (gpointer data) { GstElement *pipeline = GST_ELEMENT (data); if (gst_bin_iterate (GST_BIN (pipeline))) return TRUE; gtk_main_quit (); return FALSE; } int main (int argc, char *argv[]) { GstElement *pipeline = NULL; GError *error = NULL; GstElement *level; gst_init (&argc, &argv); gtk_init (&argc, &argv); pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error); if (error) { g_print ("pipeline could not be constructed: %s\n", error->message); g_print ("Please give a complete pipeline with a 'level' element.\n"); g_print ("Example: sinesrc ! level ! osssink\n"); g_error_free (error); return 1; } level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); if (level == NULL) { g_print ("Please give a pipeline with a 'level' element in it\n"); return 1; } g_object_set (level, "signal", TRUE, NULL); g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); /* go to main loop */ gst_element_set_state (pipeline, GST_STATE_PLAYING); g_idle_add (idler, pipeline); gtk_main (); return 0; } |
From: Thomas V. S. <tho...@us...> - 2003-09-28 08:31:13
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 28 2003 01:31:01 PDT Log message: add elapsed time Modified files: gst/level : demo.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/demo.c.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: demo.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/demo.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- demo.c 26 Sep 2003 16:45:04 -0000 1.2 +++ demo.c 28 Sep 2003 08:30:48 -0000 1.3 @@ -25,12 +25,18 @@ #include <gtk/gtk.h> /* global array for the scale widgets, we'll assume stereo */ +GtkWidget *elapsed; GtkWidget *scale[2][3]; static void level_callback (GstElement *element, gdouble time, gint channel, gdouble rms, gdouble peak, gdouble decay) { + gchar *label; + + label = g_strdup_printf ("%.3f", time); + gtk_label_set (GTK_LABEL (elapsed), label); + g_free (label); gtk_range_set_value (GTK_RANGE (scale[channel][0]), rms); gtk_range_set_value (GTK_RANGE (scale[channel][1]), peak); gtk_range_set_value (GTK_RANGE (scale[channel][2]), decay); @@ -52,6 +58,7 @@ { GtkWidget *window; GtkWidget *vbox; + GtkWidget *label, *hbox; int c; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -59,10 +66,17 @@ vbox = gtk_vbox_new (TRUE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); + + /* elapsed widget */ + hbox = gtk_hbox_new (TRUE, 0); + label = gtk_label_new ("Elapsed"); + elapsed = gtk_label_new ("0.000"); + gtk_container_add (GTK_CONTAINER (hbox), label); + gtk_container_add (GTK_CONTAINER (hbox), elapsed); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + for (c = 0; c < 2; ++c) { - GtkWidget *label, *hbox; - /* RMS */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("RMS"); |
From: Thomas V. S. <tho...@us...> - 2003-09-28 08:32:07
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Sep 28 2003 01:31:55 PDT Log message: cvs ignore Added files: gst/level : .cvsignore Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/.cvsignore?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== --- NEW FILE: .cvsignore --- gstlevel-marshal.* |
From: Thomas V. S. <tho...@us...> - 2003-10-05 16:46:36
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: thomasvs Date: Sun Oct 05 2003 09:46:33 PDT Branch: BRANCH-GSTREAMER-0_6 Log message: fixes #123901 update level plugin for the new millenium Modified files: gst/level : Makefile.am README filter.func gstlevel.c gstlevel.h Added files: gst/level : demo.c gstlevel-marshal.list plot.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.6&r2=1.6.8.1 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/README.diff?r1=1.1.1.1&r2=1.1.1.1.20.1 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/demo.c?rev=1.3.2.1&content-type=text/vnd.viewcvs-markup http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/filter.func.diff?r1=1.2.12.1&r2=1.2.12.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list?rev=1.2.2.1&content-type=text/vnd.viewcvs-markup http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.13.4.1&r2=1.13.4.2 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.h.diff?r1=1.3&r2=1.3.16.1 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/plot.c?rev=1.1.2.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.6 retrieving revision 1.6.8.1 diff -u -d -r1.6 -r1.6.8.1 --- Makefile.am 8 Dec 2002 14:49:41 -0000 1.6 +++ Makefile.am 5 Oct 2003 16:46:21 -0000 1.6.8.1 @@ -2,11 +2,43 @@ plugin_LTLIBRARIES = libgstlevel.la -libgstlevel_la_SOURCES = gstlevel.c +libgstlevel_la_SOURCES = gstlevel.c gstlevel-marshal.c libgstlevel_la_CFLAGS = $(GST_CFLAGS) libgstlevel_la_LIBADD = libgstlevel_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstlevel.h filter.func + +if HAVE_GTK +noinst_PROGRAMS = demo plot +demo_SOURCES = demo.c +demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) +plot_SOURCES = plot.c +plot_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) +endif + +EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list + +BUILT_SOURCES = \ + gstlevel-marshal.c \ + gstlevel-marshal.h + +gstlevel-marshal.h: gstlevel-marshal.list + glib-genmarshal --header --prefix=gstlevel_cclosure_marshal $(srcdir)/gstlevel-marshal.list > gstlevel-marshal.h.tmp + mv gstlevel-marshal.h.tmp gstlevel-marshal.h + +gstlevel-marshal.c: gstlevel-marshal.list + echo "#include \"glib.h\"" > gstlevel-marshal.c.tmp + echo "#include \"glib-object.h\"" >> gstlevel-marshal.c.tmp + echo "#include \"gstlevel-marshal.h\"" >> gstlevel-marshal.c.tmp + glib-genmarshal --body --prefix=gstlevel_cclosure_marshal $(srcdir)/gstlevel-marshal.list >> gstlevel-marshal.c.tmp + mv gstlevel-marshal.c.tmp gstlevel-marshal.c + +# Don't want the generated marshal files in the dist +dist-hook: + rm -f $(distdir)/gstlevel-marshal.c + rm -f $(distdir)/gstlevel-marshal.h EXTRA_DIST = README Index: README =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/README,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.20.1 diff -u -d -r1.1.1.1 -r1.1.1.1.20.1 --- README 22 Dec 2001 23:23:39 -0000 1.1.1.1 +++ README 5 Oct 2003 16:46:21 -0000 1.1.1.1.20.1 @@ -1,11 +1,39 @@ -level plugin by thomas <th...@ap...> +level plugin by thomas <thomas at apestaart dot org> -basic level indicator; prints out RMS values averaged over the buffer of -one iteration. Insert this into an audio/raw chain. +this plugin signals: + - running time since last EOS/start + - channel + - RMS level + - peak level + - decaying peak level +over the given interval. + +This is useful for a VU meter display and for plotting out the signal graph. +The VU meter can either display RMS, or display immediate peak level and +have the falloff decaying peak level displayed as a line. + +The interval for signal emission, ttl of decay peak, and falloff of decay peak +can all be set. + +The element only takes unsigned data in; it could be extended to signed as +well, if separate fast chain functions are made that displaces the incoming +data to its midpoint (ie, 0,65535 should be mapped to -32768, 32767) + +There are two demo apps, apps and plot. apps will create some GTK sliders +to display the volume. plot will output data readable by gnuplot. + +Here is a sample plot script to plot output of the plot command that was +stored to plot.dat + +set xlabel "Seconds" +set ylabel "dB" +set yrange [-60:0] +plot 'plot.dat' using 1:2 title 'L RMS' with lines, \ + 'plot.dat' using 1:3 title 'L peak' with lines, \ + 'plot.dat' using 1:4 title 'L decay' with lines + +plot 'plot.dat' using 1:5 title 'R RMS' with lines, \ + 'plot.dat' using 1:6 title 'R peak' with lines, \ + 'plot.dat' using 1:7 title 'R decay' with lines -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 --- NEW FILE: demo.c --- /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * * demo.c: sample application to display VU meter-like output of level * Copyright (C) 2003 * Thomas Vander Stichele <thomas at apestaart dot org> * * 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 <gtk/gtk.h> /* global array for the scale widgets, we'll assume stereo */ GtkWidget *elapsed; GtkWidget *scale[2][3]; static void level_callback (GstElement *element, gdouble time, gint channel, gdouble rms, gdouble peak, gdouble decay) { gchar *label; label = g_strdup_printf ("%.3f", time); gtk_label_set (GTK_LABEL (elapsed), label); g_free (label); gtk_range_set_value (GTK_RANGE (scale[channel][0]), rms); gtk_range_set_value (GTK_RANGE (scale[channel][1]), peak); gtk_range_set_value (GTK_RANGE (scale[channel][2]), decay); } static gboolean idler (gpointer data) { GstElement *pipeline = GST_ELEMENT (data); g_print ("+"); if (gst_bin_iterate (GST_BIN (pipeline))) return TRUE; gtk_main_quit (); return FALSE; } static void setup_gui () { GtkWidget *window; GtkWidget *vbox; GtkWidget *label, *hbox; int c; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "destroy", gtk_main_quit, NULL); vbox = gtk_vbox_new (TRUE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); /* elapsed widget */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("Elapsed"); elapsed = gtk_label_new ("0.000"); gtk_container_add (GTK_CONTAINER (hbox), label); gtk_container_add (GTK_CONTAINER (hbox), elapsed); gtk_container_add (GTK_CONTAINER (vbox), hbox); for (c = 0; c < 2; ++c) { /* RMS */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("RMS"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][0] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][0], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][0]); gtk_container_add (GTK_CONTAINER (vbox), hbox); /* peak */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("peak"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][1] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][1], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][1]); gtk_container_add (GTK_CONTAINER (vbox), hbox); /* decay */ hbox = gtk_hbox_new (TRUE, 0); label = gtk_label_new ("decaying peek"); gtk_container_add (GTK_CONTAINER (hbox), label); scale[c][2] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); gtk_widget_set_size_request (scale[c][2], 100, -1); gtk_container_add (GTK_CONTAINER (hbox), scale[c][2]); gtk_container_add (GTK_CONTAINER (vbox), hbox); } gtk_widget_show_all (GTK_WIDGET (window)); } int main (int argc, char *argv[]) { GstElement *pipeline = NULL; GError *error = NULL; GstElement *level; gst_init (&argc, &argv); gtk_init (&argc, &argv); pipeline = GST_ELEMENT (gst_parse_launchv ((const gchar **) &argv[1], &error)); if (error) { g_print ("pipeline could not be constructed: %s\n", error->message); g_print ("Please give a complete pipeline with a 'level' element.\n"); g_print ("Example: sinesrc ! level ! osssink\n"); g_error_free (error); return 1; } level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); if (level == NULL) { g_print ("Please give a pipeline with a 'level' element in it\n"); return 1; } g_object_set (level, "signal", TRUE, NULL); g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); /* setup GUI */ setup_gui (); /* connect level signal */ /* go to main loop */ gst_element_set_state (pipeline, GST_STATE_PLAYING); g_idle_add (idler, pipeline); gtk_main (); return 0; } Index: filter.func =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/filter.func,v retrieving revision 1.2.12.1 retrieving revision 1.2.12.2 diff -u -d -r1.2.12.1 -r1.2.12.2 --- filter.func 26 Aug 2003 20:19:43 -0000 1.2.12.1 +++ filter.func 5 Oct 2003 16:46:21 -0000 1.2.12.2 @@ -1,45 +1,34 @@ +/* process one (interleaved) channel of incoming samples + * calculate square sum of samples + * normalize and return normalized Cumulative Square + * caller must assure num is a multiple of channels + * this filter only accepts signed audio data, so mid level is always 0 + */ { - 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; + register int j; + double squaresum = 0.0; /* square sum of the integer samples */ + register double square = 0.0; /* Square */ + register double PSS = 0.0; /* Peak Square Sample */ + + *CS = 0.0; /* Cumulative Square for this block */ + + gdouble normalizer = (double) (1 << resolution); /* * process data here * input sample data enters in *in_data as 8 or 16 bit data * samples for left and right channel are interleaved + * returns the Mean Square of the samples as a double between 0 and 1 */ -/* - 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) + for (j = 0; j < num; j += channels) { -/* printf ("Reached %d dB at %f sec (%f dB)\n", - threshold_dB, timepoint, RMS_dB); -*/ - threshold_dB += 1; + square = (double) (in[j] * in[j]); + if (square > PSS) PSS = square; + squaresum += square; } -/* printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); */ - printf ("%f s %f dB\n", timepoint, RMS_dB); + *peak = PSS / ((double) normalizer * (double) normalizer); + + /* return normalized cumulative square */ + *CS = squaresum / ((double) normalizer * (double) normalizer); } - --- NEW FILE: gstlevel-marshal.list --- VOID:DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE Index: gstlevel.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.13.4.1 retrieving revision 1.13.4.2 diff -u -d -r1.13.4.1 -r1.13.4.2 --- gstlevel.c 26 Aug 2003 20:19:43 -0000 1.13.4.1 +++ gstlevel.c 5 Oct 2003 16:46:21 -0000 1.13.4.2 @@ -1,6 +1,10 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * + * gstlevel.c: signals RMS, peak and decaying peak levels + * Copyright (C) 2000,2001,2002,2003 + * Thomas Vander Stichele <thomas at apestaart dot org> + * * 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 @@ -26,65 +30,73 @@ "Level", "Filter/Audio/Analysis", "LGPL", - "RMS Level indicator for audio/raw", + "RMS/Peak/Decaying Peak Level signaller for audio/raw", VERSION, "Thomas <th...@ap...>", - "(C) 2001", + "(C) 2001, 2003, 2003", }; +/* pad templates */ + +GST_PAD_TEMPLATE_FACTORY (sink_template_factory, + "level_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "level_sink", + "audio/raw", + "format", GST_PROPS_STRING ("int"), + "signed", GST_PROPS_BOOLEAN (TRUE), + "width", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "depth", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "rate", GST_PROPS_INT_RANGE (1, G_MAXINT), + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +) + +GST_PAD_TEMPLATE_FACTORY (src_template_factory, + "level_src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "level_src", + "audio/raw", + "format", GST_PROPS_STRING ("int"), + "signed", GST_PROPS_BOOLEAN (TRUE), + "width", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "depth", GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16) + ), + "rate", GST_PROPS_INT_RANGE (1, G_MAXINT), + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +) /* Filter signals and args */ enum { /* FILL ME */ + SIGNAL_LEVEL, LAST_SIGNAL }; enum { - ARG_0 + ARG_0, + ARG_SIGNAL_LEVEL, + ARG_SIGNAL_INTERVAL, + ARG_PEAK_TTL, + ARG_PEAK_FALLOFF }; -static GstPadTemplate* -level_src_factory (void) -{ - static GstPadTemplate *template = NULL; - - if (!template) { - template = gst_pad_template_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_pad_template_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); @@ -92,13 +104,9 @@ 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 guint gst_filter_signals[LAST_SIGNAL] = { 0 }; GType gst_level_get_type (void) @@ -125,6 +133,8 @@ { GstLevel *filter; GstPad *otherpad; + GstPadLinkReturn res; + int i; filter = GST_LEVEL (gst_pad_get_parent (pad)); g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED); @@ -133,73 +143,175 @@ if (GST_CAPS_IS_FIXED (caps)) { - /*if ( !volume_parse_caps (filter, caps) || */ - return gst_pad_try_set_caps (otherpad, caps); + /* yep, got them */ + res = gst_pad_try_set_caps (otherpad, caps); + /* if ok, set filter */ + if (res == GST_PAD_LINK_OK) + { + filter->num_samples = 0; + /* FIXME: error handling */ + if (! gst_caps_get_int (caps, "rate", &(filter->rate))) + g_warning ("WARNING: level: Could not get rate from caps\n"); + if (!gst_caps_get_int (caps, "width", &(filter->width))) + g_warning ("WARNING: level: Could not get width from caps\n"); + if (!gst_caps_get_int (caps, "channels", &(filter->channels))) + g_warning ("WARNING: level: Could not get number of channels from caps\n"); + + /* allocate channel variable arrays */ + if (filter->CS) g_free (filter->CS); + if (filter->peak) g_free (filter->peak); + if (filter->last_peak) g_free (filter->last_peak); + if (filter->decay_peak) g_free (filter->decay_peak); + if (filter->decay_peak_age) g_free (filter->decay_peak_age); + if (filter->MS) g_free (filter->MS); + if (filter->RMS_dB) g_free (filter->RMS_dB); + filter->CS = g_new (double, filter->channels); + filter->peak = g_new (double, filter->channels); + filter->last_peak = g_new (double, filter->channels); + filter->decay_peak = g_new (double, filter->channels); + filter->decay_peak_age = g_new (double, filter->channels); + filter->MS = g_new (double, filter->channels); + filter->RMS_dB = g_new (double, filter->channels); + for (i = 0; i < filter->channels; ++i) + { + filter->CS[i] = filter->peak[i] = filter->last_peak[i] = + filter->decay_peak[i] = filter->decay_peak_age[i] = + filter->MS[i] = filter->RMS_dB[i] = 0.0; + } + } + return res; } return GST_PAD_LINK_DELAYED; } +static void inline +gst_level_fast_16bit_chain (gint16* in, guint num, gint channels, + gint resolution, double *CS, double *peak) +#include "filter.func" + +static void inline +gst_level_fast_8bit_chain (gint8* in, guint num, gint channels, + gint resolution, double *CS, double *peak) +#include "filter.func" + static void gst_level_chain (GstPad *pad, GstBuffer *buf) { GstLevel *filter; gint16 *in_data; - gint16 *out_data; - GstBuffer* outbuf; - gint width; - GstCaps *caps; + double CS = 0.0; + gint num_samples = 0; + gint i; 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) + for (i = 0; i < filter->channels; ++i) + filter->CS[i] = filter->peak[i] = filter->MS[i] = filter->RMS_dB[i] = 0.0; + + in_data = (gint16 *) GST_BUFFER_DATA (buf); + + num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); + if (num_samples % filter->channels != 0) + g_warning ("WARNING: level: programming error, data not properly interleaved"); + + for (i = 0; i < filter->channels; ++i) { - /* FIXME : Please change this to a better warning method ! */ - g_error ("WARNING: level: Could not get pad caps - caps nego failed !\n"); + switch (filter->width) + { + case 16: + gst_level_fast_16bit_chain (in_data + i, num_samples, + filter->channels, filter->width - 1, + &CS, &filter->peak[i]); + break; + case 8: + gst_level_fast_8bit_chain (((gint8 *) in_data) + i, num_samples, + filter->channels, filter->width - 1, + &CS, &filter->peak[i]); + break; + } + /* g_print ("DEBUG: CS %f, peak %f\n", CS, filter->peak[i]); */ + filter->CS[i] += CS; + } + gst_pad_push (filter->srcpad, buf); - gst_caps_get_int (caps, "width", &width); + filter->num_samples += num_samples; - 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); + for (i = 0; i < filter->channels; ++i) + { + filter->decay_peak_age[i] += num_samples; + /* g_print ("filter peak info [%d]: peak %f, age %f\n", i, + filter->last_peak[i], filter->decay_peak_age[i]); */ + /* update running peak */ + if (filter->peak[i] > filter->last_peak[i]) + filter->last_peak[i] = filter->peak[i]; - out_data = (gint16 *) GST_BUFFER_DATA (outbuf); + /* update decay peak */ + if (filter->peak[i] >= filter->decay_peak[i]) + { + /* g_print ("new peak, %f\n", filter->peak[i]); */ + filter->decay_peak[i] = filter->peak[i]; + filter->decay_peak_age[i] = 0; + } + else + { + /* make decay peak fall off if too old */ + if (filter->decay_peak_age[i] > filter->rate * filter->decay_peak_ttl) + { + double falloff_dB; + double falloff; + double length; /* length of buffer in seconds */ + + + length = (double) num_samples / (filter->channels * filter->rate); + falloff_dB = filter->decay_peak_falloff * length; + falloff = pow (10, falloff_dB / -20.0); + + /* g_print ("falloff: length %f, dB falloff %f, falloff factor %e\n", + length, falloff_dB, falloff); */ + filter->decay_peak[i] *= falloff; + /* g_print ("peak is %f samples old, decayed with factor %e to %f\n", + filter->decay_peak_age[i], falloff, filter->decay_peak[i]); */ + } + } + } + + /* do we need to emit ? */ - g_print ("%s: ", gst_element_get_name (GST_ELEMENT (filter))); - 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; + if (filter->num_samples >= filter->interval * (gdouble) filter->rate) + { + if (filter->signal) + { + gdouble RMS, peak, endtime; + for (i = 0; i < filter->channels; ++i) + { + RMS = sqrt (filter->CS[i] / (filter->num_samples / filter->channels)); + peak = filter->last_peak[i]; + num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); + endtime = (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND + + (double) num_samples / (double) filter->rate; + + g_signal_emit (G_OBJECT (filter), gst_filter_signals[SIGNAL_LEVEL], 0, + endtime, i, + 20 * log10 (RMS), 20 * log10 (filter->last_peak[i]), + 20 * log10 (filter->decay_peak[i])); + /* we emitted, so reset cumulative and normal peak */ + filter->CS[i] = 0.0; + filter->last_peak[i] = 0.0; + } + } + filter->num_samples = 0; } - 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, @@ -212,6 +324,18 @@ filter = GST_LEVEL (object); switch (prop_id) { + case ARG_SIGNAL_LEVEL: + filter->signal = g_value_get_boolean (value); + break; + case ARG_SIGNAL_INTERVAL: + filter->interval = g_value_get_double (value); + break; + case ARG_PEAK_TTL: + filter->decay_peak_ttl = g_value_get_double (value); + break; + case ARG_PEAK_FALLOFF: + filter->decay_peak_falloff = g_value_get_double (value); + break; default: break; } @@ -228,7 +352,19 @@ filter = GST_LEVEL (object); switch (prop_id) { - default: + case ARG_SIGNAL_LEVEL: + g_value_set_boolean (value, filter->signal); + break; + case ARG_SIGNAL_INTERVAL: + g_value_set_double (value, filter->interval); + break; + case ARG_PEAK_TTL: + g_value_set_double (value, filter->decay_peak_ttl); + break; + case ARG_PEAK_FALLOFF: + g_value_set_double (value, filter->decay_peak_falloff); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } @@ -244,23 +380,60 @@ gstelement_class = (GstElementClass*) klass; parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_LEVEL, + g_param_spec_boolean ("signal", "Signal", + "Emit level signals for each interval", + TRUE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_INTERVAL, + g_param_spec_double ("interval", "Interval", + "Interval between emissions (in seconds)", + 0.01, 100.0, 0.1, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PEAK_TTL, + g_param_spec_double ("peak_ttl", "Peak TTL", + "Time To Live of decay peak before it falls back", + 0, 100.0, 0.3, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PEAK_FALLOFF, + g_param_spec_double ("peak_falloff", "Peak Falloff", + "Decay rate of decay peak after TTL (in dB/sec)", + 0.0, G_MAXDOUBLE, 10.0, G_PARAM_READWRITE)); gobject_class->set_property = gst_level_set_property; gobject_class->get_property = gst_level_get_property; + + gst_filter_signals[SIGNAL_LEVEL] = + g_signal_new ("level", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstLevelClass, level), NULL, NULL, + gstlevel_cclosure_marshal_VOID__DOUBLE_INT_DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, 5, + G_TYPE_DOUBLE, G_TYPE_INT, + G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); } static void gst_level_init (GstLevel *filter) { - filter->sinkpad = gst_pad_new_from_template (level_sink_factory (), "sink"); + filter->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_template_factory), "sink"); gst_pad_set_link_function (filter->sinkpad, gst_level_connect); - filter->srcpad = gst_pad_new_from_template (level_src_factory (), "src"); + filter->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_template_factory), "src"); gst_pad_set_link_function (filter->srcpad, gst_level_connect); 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); + + filter->CS = NULL; + filter->peak = NULL; + filter->MS = NULL; + filter->RMS_dB = NULL; + + filter->rate = 0; + filter->width = 0; + filter->channels = 0; + + filter->interval = 0.1; + filter->decay_peak_ttl = 0.4; + filter->decay_peak_falloff = 10.0; /* dB falloff (/sec) */ } static gboolean @@ -272,8 +445,8 @@ &level_details); g_return_val_if_fail (factory != NULL, FALSE); - gst_element_factory_add_pad_template (factory, level_src_factory ()); - gst_element_factory_add_pad_template (factory, level_sink_factory ()); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template_factory)); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template_factory)); gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); Index: gstlevel.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/gst/level/gstlevel.h,v retrieving revision 1.3 retrieving revision 1.3.16.1 diff -u -d -r1.3 -r1.3.16.1 --- gstlevel.h 20 Mar 2002 21:44:51 -0000 1.3 +++ gstlevel.h 5 Oct 2003 16:46:21 -0000 1.3.16.1 @@ -1,6 +1,10 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * + * gstlevel.c: signals RMS, peak and decaying peak levels + * Copyright (C) 2000,2001,2002,2003 + * Thomas Vander Stichele <thomas at apestaart dot org> + * * 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 @@ -24,8 +28,8 @@ #include <config.h> #include <gst/gst.h> -/* #include <gst/meta/audioraw.h> */ +#include "gstlevel-marshal.h" #ifdef __cplusplus extern "C" { @@ -49,14 +53,32 @@ struct _GstLevel { GstElement element; - GstPad *sinkpad,*srcpad; + GstPad *sinkpad, *srcpad; + gboolean signal; /* whether or not to emit signals */ + gdouble interval; /* how many seconds between emits */ - /*MetaAudioRaw meta; */ + gint rate; /* caps variables */ + gint width; + gint channels; + gdouble decay_peak_ttl; /* time to live for peak in seconds */ + gdouble decay_peak_falloff; /* falloff in dB/sec */ + gdouble num_samples; /* cumulative sample count */ + + /* per-channel arrays for intermediate values */ + gdouble *CS; /* normalized Cumulative Square */ + gdouble *peak; /* normalized Peak value over buffer */ + gdouble *last_peak; /* last normalized Peak value over interval */ + gdouble *decay_peak; /* running decaying normalized Peak */ + gdouble *MS; /* normalized Mean Square of buffer */ + gdouble *RMS_dB; /* RMS in dB to emit */ + gdouble *decay_peak_age; /* age of last peak */ }; struct _GstLevelClass { GstElementClass parent_class; + void (*level) (GstElement *element, gdouble time, gint channel, + gdouble RMS_dB, gdouble peak_dB, gdouble decay_peak_dB); }; GType gst_level_get_type(void); --- NEW FILE: plot.c --- /* GStreamer * Copyright (C) <1999> Erik Walthinsen <om...@cs...> * * plot.c: output data points to be graphed with gnuplot * Copyright (C) 2003 * Thomas Vander Stichele <thomas at apestaart dot org> * * 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 <gtk/gtk.h> gboolean got_channel[2] = { FALSE, FALSE}; /* to see if we got the signal for this one yet */ gint channels = 0 ; /* guess at how many channels there are */ gdouble last_time = 0.0; /* time of last signal */ gdouble values[2][3]; /* array of levels from which to print */ static void level_callback (GstElement *element, gdouble time, gint channel, gdouble rms, gdouble peak, gdouble decay) { int i = 0, j = 0; gboolean got_all = FALSE; if (channel + 1> channels) channels = channel + 1; /* reset got_channel if this is a new time point */ if (time > last_time) { for (i = 0; i < channels; ++i) got_channel[i] = FALSE; last_time = time; } /* store values */ got_channel[channel] = TRUE; values[channel][0] = rms; values[channel][1] = peak; values[channel][2] = decay; /* check if we have all channels, and output if we do */ /* FIXME: this fails on the first, no ? */ got_all = TRUE; for (i = 0; i < channels; ++i) if (!got_channel[i]) got_all = FALSE; if (got_all) { g_print ("%f ", time); for (i = 0; i < channels; ++i) for (j = 0; j < 3; ++j) g_print ("%f ", values[i][j]); g_print ("\n"); } } static gboolean idler (gpointer data) { GstElement *pipeline = GST_ELEMENT (data); if (gst_bin_iterate (GST_BIN (pipeline))) return TRUE; gtk_main_quit (); return FALSE; } int main (int argc, char *argv[]) { GstElement *pipeline = NULL; GError *error = NULL; GstElement *level; gst_init (&argc, &argv); gtk_init (&argc, &argv); pipeline = GST_ELEMENT (gst_parse_launchv ((const gchar **) &argv[1], &error)); if (error) { g_print ("pipeline could not be constructed: %s\n", error->message); g_print ("Please give a complete pipeline with a 'level' element.\n"); g_print ("Example: sinesrc ! level ! osssink\n"); g_error_free (error); return 1; } level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); if (level == NULL) { g_print ("Please give a pipeline with a 'level' element in it\n"); return 1; } g_object_set (level, "signal", TRUE, NULL); g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); /* go to main loop */ gst_element_set_state (pipeline, GST_STATE_PLAYING); g_idle_add (idler, pipeline); gtk_main (); return 0; } |
From: Thomas V. S. <tho...@pd...> - 2004-06-09 17:06:42
|
CVS Root: /home/cvs/gstreamer Module: gst-plugins Changes by: thomasvs Date: Thu Jun 10 2004 03:06:40 EST Log message: trigger change Modified files: gst/level : Makefile.am gstlevel-marshal.list Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.14&r2=1.15 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- a/Makefile.am 8 Jun 2004 10:14:50 -0000 1.14 +++ b/Makefile.am 9 Jun 2004 17:06:28 -0000 1.15 @@ -29,8 +29,6 @@ plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) endif -EXTRA_libgstlevel_la_SOURCES = gstlevel-marshal.list - CLEANFILES = $(BUILT_SOURCES) -EXTRA_DIST = README +EXTRA_DIST = README gst-level-marshal.list Index: gstlevel-marshal.list RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/gstlevel-marshal.list 26 Sep 2003 16:45:04 -0000 1.2 +++ b/gstlevel-marshal.list 9 Jun 2004 17:06:28 -0000 1.3 @@ -1 +1,2 @@ VOID:DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE + |
From: Thomas V. S. <tho...@pd...> - 2004-06-09 17:07:05
|
CVS Root: /home/cvs/gstreamer Module: gst-plugins Changes by: thomasvs Date: Thu Jun 10 2004 03:07:00 EST Log message: trigger change Modified files: gst/level : gstlevel-marshal.list Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: gstlevel-marshal.list =================================================================== RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/gstlevel-marshal.list,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/gstlevel-marshal.list 9 Jun 2004 17:06:28 -0000 1.3 +++ b/gstlevel-marshal.list 9 Jun 2004 17:06:48 -0000 1.4 @@ -1,2 +1 @@ VOID:DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE - |
From: Thomas V. S. <tho...@pd...> - 2004-06-09 20:34:42
|
CVS Root: /home/cvs/gstreamer Module: gst-plugins Changes by: thomasvs Date: Thu Jun 10 2004 06:34:41 EST Log message: sigh sigh Modified files: gst/level : Makefile.am Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/Makefile.am.diff?r1=1.15&r2=1.16 ====Begin Diffs==== Index: Makefile.am =================================================================== RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/Makefile.am,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- a/Makefile.am 9 Jun 2004 17:06:28 -0000 1.15 +++ b/Makefile.am 9 Jun 2004 20:34:29 -0000 1.16 @@ -31,4 +31,4 @@ CLEANFILES = $(BUILT_SOURCES) -EXTRA_DIST = README gst-level-marshal.list +EXTRA_DIST = README gstlevel-marshal.list |
From: <tho...@fr...> - 2004-07-27 16:41:30
|
CVS Root: /home/cvs/gstreamer Module: gst-plugins Changes by: thomasvs Date: Wed Jul 28 2004 02:41:29 EST Log message: comments Modified files: gst/level : filter.func gstlevel.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/filter.func.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.33&r2=1.34 ====Begin Diffs==== Index: filter.func =================================================================== RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/filter.func,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- filter.func 14 Oct 2003 10:07:59 -0000 1.5 +++ filter.func 27 Jul 2004 16:41:15 -0000 1.6 @@ -1,3 +1,8 @@ +/* +static void inline +gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels, + gint resolution, double *CS, double *peak) +*/ /* process one (interleaved) channel of incoming samples * calculate square sum of samples * normalize and return normalized Cumulative Square Index: gstlevel.c RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- gstlevel.c 26 Jul 2004 18:34:01 -0000 1.33 +++ gstlevel.c 27 Jul 2004 16:41:15 -0000 1.34 @@ -201,6 +201,7 @@ in_data = (gint16 *) GST_BUFFER_DATA (buf); + /* total number of interleaved samples */ num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); if (num_samples % filter->channels != 0) g_warning |
From: <tho...@fr...> - 2004-07-27 17:43:03
|
CVS Root: /home/cvs/gstreamer Module: gst-plugins Changes by: thomasvs Date: Wed Jul 28 2004 03:42:59 EST Log message: fix template, only signed accepted Modified files: gst/level : filter.func gstlevel.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/filter.func.diff?r1=1.6&r2=1.7 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.34&r2=1.35 ====Begin Diffs==== Index: filter.func =================================================================== RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/filter.func,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- filter.func 27 Jul 2004 16:41:15 -0000 1.6 +++ filter.func 27 Jul 2004 17:42:47 -0000 1.7 @@ -29,6 +29,7 @@ for (j = 0; j < num; j += channels) { + //g_print ("ch %d -> smp %d\n", j, in[j]); square = (double) (in[j] * in[j]); if (square > PSS) PSS = square; squaresum += square; Index: gstlevel.c RCS file: /home/cvs/gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- gstlevel.c 27 Jul 2004 16:41:15 -0000 1.34 +++ gstlevel.c 27 Jul 2004 17:42:47 -0000 1.35 @@ -46,14 +46,24 @@ GST_STATIC_PAD_TEMPLATE ("level_sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS) + GST_STATIC_CAPS ("audio/x-raw-int, " + "rate = (int) [ 1, MAX ], " + "channels = (int) 2, " + "endianness = (int) BYTE_ORDER, " + "width = (int) { 8, 16 }, " + "depth = (int) { 8, 16 }, " "signed = (boolean) true") ); static GstStaticPadTemplate src_template_factory = GST_STATIC_PAD_TEMPLATE ("level_src", GST_PAD_SRC, /* Filter signals and args */ |
From: <tho...@fr...> - 2005-08-10 10:52:32
|
CVS Root: /cvs//gstreamer Module: gst-plugins Changes by: thomasvs Date: Wed Aug 10 2005 03:52:28 PDT Branch: BRANCH-GSTREAMER-0_8 Log message: some more multichannel fixes Modified files: gst/level : gstlevel.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/gst/level/gstlevel.c.diff?r1=1.37.4.1&r2=1.37.4.2 ====Begin Diffs==== Index: gstlevel.c =================================================================== RCS file: /cvs//gstreamer/gst-plugins/gst/level/gstlevel.c,v retrieving revision 1.37.4.1 retrieving revision 1.37.4.2 diff -u -d -r1.37.4.1 -r1.37.4.2 --- gstlevel.c 10 Aug 2005 10:19:22 -0000 1.37.4.1 +++ gstlevel.c 10 Aug 2005 10:52:16 -0000 1.37.4.2 @@ -186,7 +186,7 @@ gint16 *in_data; double CS = 0.0; - gint num_int_samples = 0; + gint num_int_samples = 0; /* total number of interleaved samples */ gint i; g_return_if_fail (pad != NULL); @@ -209,7 +209,6 @@ in_data = (gint16 *) GST_BUFFER_DATA (buf); - /* total number of interleaved samples */ num_int_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); if (num_int_samples % filter->channels != 0) g_warning @@ -235,10 +234,10 @@ } gst_pad_push (filter->srcpad, GST_DATA (buf)); - filter->num_samples += num_int_samples; + filter->num_samples += num_int_samples / filter->channels; for (i = 0; i < filter->channels; ++i) { - filter->decay_peak_age[i] += num_int_samples; + filter->decay_peak_age[i] += num_int_samples / filter->channels; /* update running peak */ if (filter->peak[i] > filter->last_peak[i]) filter->last_peak[i] = filter->peak[i]; @@ -277,18 +276,17 @@ if (filter->num_samples >= filter->interval * (gdouble) filter->rate) { if (filter->signal) { - gdouble RMS, peak, endtime; + gdouble RMS, endtime; gdouble RMSdB, lastdB, decaydB; + endtime = (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND + + (double) num_int_samples / (filter->rate * filter->channels); + for (i = 0; i < filter->channels; ++i) { - RMS = sqrt (filter->CS[i] / (filter->num_samples / filter->channels)); + RMS = sqrt (filter->CS[i] / filter->num_samples); GST_LOG_OBJECT (filter, "CS: %f, num_samples %f, channel %d, RMS %f", filter->CS[i], filter->num_samples, i, RMS); - peak = filter->last_peak[i]; - num_int_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); - endtime = (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND - + (double) num_int_samples / (double) filter->rate; /* RMS values are calculated in amplitude, so 20 * log 10 */ RMSdB = 20 * log10 (RMS); |