Commit 0428d5cf authored by Stefan Kost's avatar Stefan Kost

Initial port of the spectrum element

Original commit message from CVS:
* configure.ac:
* gst/spectrum/demo-osssrc.c: (spectrum_chain), (main):
* gst/spectrum/fix_fft.c: (gst_spectrum_fix_dot):
* gst/spectrum/gstspectrum.c: (gst_spectrum_get_type),
(gst_spectrum_base_init), (gst_spectrum_class_init),
(gst_spectrum_init), (gst_spectrum_dispose),
(gst_spectrum_set_property), (gst_spectrum_chain):
* gst/spectrum/gstspectrum.h:
Initial port of the spectrum element
parent 4e5f3fae
2006-05-21 Stefan Kost <ensonic@users.sf.net>
* configure.ac:
* gst/spectrum/demo-osssrc.c: (spectrum_chain), (main):
* gst/spectrum/fix_fft.c: (gst_spectrum_fix_dot):
* gst/spectrum/gstspectrum.c: (gst_spectrum_get_type),
(gst_spectrum_base_init), (gst_spectrum_class_init),
(gst_spectrum_init), (gst_spectrum_dispose),
(gst_spectrum_set_property), (gst_spectrum_chain):
* gst/spectrum/gstspectrum.h:
Initial port of the spectrum element
2006-05-19 Edgard Lima <edgard.lima@indt.org.br>
* sys/v4l2/gstv4l2.c:
......
......@@ -79,6 +79,7 @@ GST_PLUGINS_ALL="\
cdxaparse \
freeze \
modplug \
spectrum \
speed \
qtdemux \
xingheader \
......@@ -154,16 +155,41 @@ dnl uninstalled is selected preferentially -- see pkg-config(1)
GST_CHECK_GST($GST_MAJORMINOR, [$GST_REQ])
GST_CHECK_GST_BASE($GST_MAJORMINOR, [$GST_REQ])
GST_CHECK_GST_CHECK($GST_MAJORMINOR, [$GST_REQ], no)
GST_CHECK_GST_PLUGINS_BASE($GST_MAJORMINOR, [$GSTPB_REQ], no)
GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_MAJORMINOR --variable pluginsdir`
AC_SUBST(GSTPB_PLUGINS_DIR)
AC_MSG_NOTICE(Using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR)
dnl FIXME: get rid of this by making sure gstreamer-check brings it in
dnl check for "check", unit testing library/header
AM_PATH_CHECK(0.9.2, HAVE_CHECK=yes, HAVE_CHECK=no)
AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_CHECK" = "xyes")
GST_CHECK_GST_PLUGINS_BASE($GST_MAJORMINOR, [$GSTPB_REQ], no)
GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_MAJORMINOR --variable pluginsdir`
AC_SUBST(GSTPB_PLUGINS_DIR)
AC_MSG_NOTICE(Using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR)
dnl GTK is optional and used in examples
HAVE_GTK=NO
PKG_CHECK_MODULES(GTK2, gtk+-2.0 >= 2.2.0, HAVE_GTK_22=yes, HAVE_GTK_22=no)
if test "x$HAVE_GTK_22" = "xyes"; then
HAVE_GTK=yes
GTK_VERSION=`$PKG_CONFIG --variable=gtk_binary_version gtk+-2.0`
AC_SUBST(GTK_VERSION)
GTK_PREFIX=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
AC_SUBST(GTK_BASE_DIR)
GDK_PIXBUF_LIBDIR=`$PKG_CONFIG --variable=libdir gdk-pixbuf-2.0`
GDK_PIXBUF_PREFIXDIR=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
AC_SUBST(GTK_BASE_DIR)
else
PKG_CHECK_MODULES(GTK2, gtk+-2.0, HAVE_GTK_20=yes, HAVE_GTK_20=no)
fi
if test "x$HAVE_GTK_20" = "xyes"; then
HAVE_GTK=yes
fi
GTK_CFLAGS=$GTK2_CFLAGS
GTK_LIBS=$GTK2_LIBS
AC_SUBST(GTK_LIBS)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(HAVE_GTK)
AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes")
dnl set license and copyright notice
GST_LICENSE="LGPL"
......@@ -679,6 +705,7 @@ gst/cdxaparse/Makefile
gst/freeze/Makefile
gst/modplug/Makefile
gst/modplug/libmodplug/Makefile
gst/spectrum/Makefile
gst/speed/Makefile
gst/qtdemux/Makefile
gst/tta/Makefile
......
......@@ -4,26 +4,26 @@
#include <gst/gst.h>
#include <gtk/gtk.h>
extern gboolean _gst_plugin_spew;
gboolean idle_func (gpointer data);
#define DEFAULT_AUDIOSRC "alsasrc"
#define SPECT_BANDS 256
GtkWidget *drawingarea;
void
static void
spectrum_chain (GstElement * sink, GstBuffer * buf, GstPad * pad,
gpointer unused)
{
gint i;
guchar *data = buf->data;
GdkRectangle rect = { 0, 0, GST_BUFFER_SIZE (buf), 25 };
gint width = GST_BUFFER_SIZE (buf);
GdkRectangle rect = { 0, 0, width, 50 };
gdk_window_begin_paint_rect (drawingarea->window, &rect);
gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc,
TRUE, 0, 0, GST_BUFFER_SIZE (buf), 25);
for (i = 0; i < GST_BUFFER_SIZE (buf); i++) {
TRUE, 0, 0, width, 50);
for (i = 0; i < width; i++) {
gdk_draw_rectangle (drawingarea->window, drawingarea->style->white_gc,
TRUE, i, 32 - data[i], 1, data[i]);
TRUE, i, 64 - data[i], 1, data[i]);
}
gdk_window_end_paint (drawingarea->window);
}
......@@ -32,7 +32,7 @@ int
main (int argc, char *argv[])
{
GstElement *bin;
GstElement *src, *spectrum, *sink;
GstElement *src, *conv, *spectrum, *sink;
GtkWidget *appwindow;
......@@ -42,34 +42,35 @@ main (int argc, char *argv[])
bin = gst_pipeline_new ("bin");
src = gst_element_factory_make (DEFAULT_AUDIOSRC, "src");
g_object_set (G_OBJECT (src), "buffersize", (gulong) 1024, NULL);
g_object_set (G_OBJECT (src), "blocksize", (gulong) 1024 * 2, NULL);
conv = gst_element_factory_make ("audioconvert", "conv");
spectrum = gst_element_factory_make ("spectrum", "spectrum");
g_object_set (G_OBJECT (spectrum), "width", 256, NULL);
g_object_set (G_OBJECT (spectrum), "width", SPECT_BANDS, NULL);
sink = gst_element_factory_make ("fakesink", "sink");
g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
g_signal_connect (sink, "handoff", G_CALLBACK (spectrum_chain), NULL);
gst_bin_add_many (GST_BIN (bin), src, spectrum, sink, NULL);
gst_element_link_many (src, spectrum, sink, NULL);
gst_bin_add_many (GST_BIN (bin), src, conv, spectrum, sink, NULL);
if (!gst_element_link_many (src, conv, spectrum, sink, NULL)) {
fprintf (stderr, "cant link elements\n");
exit (1);
}
appwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
drawingarea = gtk_drawing_area_new ();
gtk_drawing_area_size (GTK_DRAWING_AREA (drawingarea), 256, 32);
gtk_drawing_area_size (GTK_DRAWING_AREA (drawingarea), SPECT_BANDS, 64);
gtk_container_add (GTK_CONTAINER (appwindow), drawingarea);
gtk_widget_show_all (appwindow);
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
g_idle_add (idle_func, bin);
gst_element_set_state (bin, GST_STATE_PLAYING);
gtk_main ();
gst_element_set_state (bin, GST_STATE_NULL);
return 0;
}
gst_object_unref (bin);
gboolean
idle_func (gpointer data)
{
return gst_bin_iterate (data);
return 0;
}
This diff is collapsed.
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* <2006> Stefan Kost <ensonic@users.sf.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -24,12 +25,33 @@
#include "gstspectrum.h"
GST_DEBUG_CATEGORY_STATIC (gst_spectrum_debug);
#define GST_CAT_DEFAULT gst_spectrum_debug
/* elementfactory information */
static const GstElementDetails gst_spectrum_details =
GST_ELEMENT_DETAILS ("Spectrum analyzer",
"Filter/Analyzer/Audio",
"Run an FFT on the audio signal, output spectrum data",
"Erik Walthinsen <omega@cse.ogi.edu>");
"Erik Walthinsen <omega@cse.ogi.edu>,"
"Stefan Kost <ensonic@users.sf.net>");
static GstStaticPadTemplate sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, "
"rate = (int) [ 1, MAX ], "
"channels = (int) 1, "
"endianness = (int) BYTE_ORDER, "
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
);
static GstStaticPadTemplate src_template_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
/* Spectrum signals and args */
enum
......@@ -48,18 +70,17 @@ enum
static void gst_spectrum_base_init (gpointer g_class);
static void gst_spectrum_class_init (GstSpectrumClass * klass);
static void gst_spectrum_init (GstSpectrum * spectrum);
static void gst_spectrum_dispose (GObject * object);
static void gst_spectrum_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_spectrum_chain (GstPad * pad, GstData * _data);
static GstFlowReturn gst_spectrum_chain (GstPad * pad, GstBuffer * buffer);
#define fixed short
int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse);
void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
extern int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse);
extern void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
int scale_shift);
void gst_spectrum_window (fixed fr[], int n);
extern void gst_spectrum_window (fixed fr[], int n);
static GstElementClass *parent_class = NULL;
......@@ -83,9 +104,10 @@ gst_spectrum_get_type (void)
(GInstanceInitFunc) gst_spectrum_init,
};
spectrum_type =
g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum", &spectrum_info,
0);
spectrum_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum",
&spectrum_info, 0);
GST_DEBUG_CATEGORY_INIT (gst_spectrum_debug, "spectrum", 0,
"audio spectrum analyser element");
}
return spectrum_type;
}
......@@ -95,113 +117,128 @@ gst_spectrum_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_template_factory));
gst_element_class_set_details (element_class, &gst_spectrum_details);
}
static void
gst_spectrum_class_init (GstSpectrumClass * klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH, g_param_spec_int ("width", "width", "width", G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE)); /* CHECKME */
gobject_class->set_property = gst_spectrum_set_property;
gobject_class->dispose = gst_spectrum_dispose;
g_object_class_install_property (gobject_class, ARG_WIDTH,
g_param_spec_int ("width", "width", "width",
G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));
}
static void
gst_spectrum_init (GstSpectrum * spectrum)
{
spectrum->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
spectrum->sinkpad =
gst_pad_new_from_static_template (&sink_template_factory, "sink");
gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->sinkpad);
gst_pad_set_chain_function (spectrum->sinkpad, gst_spectrum_chain);
spectrum->srcpad = gst_pad_new ("src", GST_PAD_SRC);
spectrum->srcpad =
gst_pad_new_from_static_template (&src_template_factory, "src");
gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->srcpad);
spectrum->width = 75;
spectrum->base = 8;
spectrum->len = 1024;
spectrum->loud = g_malloc (spectrum->len * sizeof (gint16));
spectrum->im = g_malloc (spectrum->len * sizeof (gint16));
memset (spectrum->im, 0, spectrum->len * sizeof (gint16));
spectrum->re = g_malloc (spectrum->len * sizeof (gint16));
memset (spectrum->re, 0, spectrum->len * sizeof (gint16));
}
static void
gst_spectrum_dispose (GObject * object)
{
GstSpectrum *spectrum = GST_SPECTRUM (object);
g_free (spectrum->re);
g_free (spectrum->im);
g_free (spectrum->loud);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_spectrum_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstSpectrum *spectrum;
g_return_if_fail (GST_IS_SPECTRUM (object));
spectrum = GST_SPECTRUM (object);
GstSpectrum *spectrum = GST_SPECTRUM (object);
switch (prop_id) {
case ARG_WIDTH:
spectrum->width = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_spectrum_chain (GstPad * pad, GstData * _data)
static GstFlowReturn
gst_spectrum_chain (GstPad * pad, GstBuffer * buffer)
{
GstBuffer *buf = GST_BUFFER (_data);
GstSpectrum *spectrum;
gint spec_base, spec_len;
gint16 *re, *im, *loud;
gint16 *samples;
gint step, pos, i;
gint step, pos, num, i;
guchar *spect;
GstBuffer *newbuf;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
spectrum = GST_SPECTRUM (GST_OBJECT_PARENT (pad));
samples = (gint16 *) GST_BUFFER_DATA (buffer);
GST_LOG ("buffer-size = %ld", GST_BUFFER_SIZE (buffer));
/* FIXME:need a gst_adapter */
num = GST_BUFFER_SIZE (buffer) / 2;
num = MIN (num, spectrum->len);
for (i = 0; i < num; i++)
spectrum->re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
gst_spectrum_window (spectrum->re, spectrum->len);
gst_spectrum_fix_fft (spectrum->re, spectrum->im, spectrum->base, FALSE);
gst_spectrum_fix_loud (spectrum->loud, spectrum->re, spectrum->im,
spectrum->len, 0);
samples = (gint16 *) GST_BUFFER_DATA (buf);
spec_base = 8;
spec_len = 1024;
im = g_malloc (spec_len * sizeof (gint16));
g_return_if_fail (im != NULL);
loud = g_malloc (spec_len * sizeof (gint16));
g_return_if_fail (loud != NULL);
memset (im, 0, spec_len * sizeof (gint16));
/*if (spectrum->meta->channels == 2) { */
re = g_malloc (spec_len * sizeof (gint16));
for (i = 0; i < spec_len; i++)
re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
/*} else */
/* re = samples; */
gst_spectrum_window (re, spec_len);
gst_spectrum_fix_fft (re, im, spec_base, FALSE);
gst_spectrum_fix_loud (loud, re, im, spec_len, 0);
if (re != samples)
g_free (re);
g_free (im);
step = spec_len / (spectrum->width * 2);
/* resample to requested width */
step = spectrum->len / (spectrum->width * 4); /* <-- shouldn't this be 2 instead of 4? */
spect = (guchar *) g_malloc (spectrum->width);
for (i = 0, pos = 0; i < spectrum->width; i++, pos += step) {
if (loud[pos] > -60)
spect[i] = (loud[pos] + 60) / 2;
else
/* > -60 db? */
if (spectrum->loud[pos] > -60) {
spect[i] = spectrum->loud[pos] + 60;
/*
if (spect[i] > 15);
spect[i] = 15;
*/
} else
/* treat as silence */
spect[i] = 0;
/* if (spect[i] > 15); */
/* spect[i] = 15; */
}
g_free (loud);
gst_buffer_unref (buf);
/* g_free(samples); */
gst_buffer_unref (buffer);
newbuf = gst_buffer_new ();
g_return_if_fail (newbuf != NULL);
GST_BUFFER_DATA (newbuf) = spect;
GST_BUFFER_SIZE (newbuf) = spectrum->width;
gst_pad_push (spectrum->srcpad, GST_DATA (newbuf));
return gst_pad_push (spectrum->srcpad, newbuf);
}
static gboolean
......
......@@ -39,7 +39,7 @@ extern "C" {
#define GST_IS_SPECTRUM(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPECTRUM))
#define GST_IS_SPECTRUM_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPECTRUM))
(G_TYPE_CHECK_CLASS_TYPE((obj),GST_TYPE_SPECTRUM))
typedef struct _GstSpectrum GstSpectrum;
typedef struct _GstSpectrumClass GstSpectrumClass;
......@@ -50,6 +50,8 @@ struct _GstSpectrum {
GstPad *sinkpad,*srcpad;
gint width;
gint base, len;
gint16 *re, *im, *loud;
};
struct _GstSpectrumClass {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment