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
This commit is contained in:
Stefan Kost 2006-05-20 22:42:15 +00:00
parent 4e5f3fae24
commit 0428d5cf5f
6 changed files with 331 additions and 249 deletions

View File

@ -1,3 +1,15 @@
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> 2006-05-19 Edgard Lima <edgard.lima@indt.org.br>
* sys/v4l2/gstv4l2.c: * sys/v4l2/gstv4l2.c:

View File

@ -79,6 +79,7 @@ GST_PLUGINS_ALL="\
cdxaparse \ cdxaparse \
freeze \ freeze \
modplug \ modplug \
spectrum \
speed \ speed \
qtdemux \ qtdemux \
xingheader \ xingheader \
@ -154,16 +155,41 @@ dnl uninstalled is selected preferentially -- see pkg-config(1)
GST_CHECK_GST($GST_MAJORMINOR, [$GST_REQ]) GST_CHECK_GST($GST_MAJORMINOR, [$GST_REQ])
GST_CHECK_GST_BASE($GST_MAJORMINOR, [$GST_REQ]) GST_CHECK_GST_BASE($GST_MAJORMINOR, [$GST_REQ])
GST_CHECK_GST_CHECK($GST_MAJORMINOR, [$GST_REQ], no) 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 FIXME: get rid of this by making sure gstreamer-check brings it in
dnl check for "check", unit testing library/header dnl check for "check", unit testing library/header
AM_PATH_CHECK(0.9.2, HAVE_CHECK=yes, HAVE_CHECK=no) AM_PATH_CHECK(0.9.2, HAVE_CHECK=yes, HAVE_CHECK=no)
AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_CHECK" = "xyes") AM_CONDITIONAL(HAVE_CHECK, test "x$HAVE_CHECK" = "xyes")
GST_CHECK_GST_PLUGINS_BASE($GST_MAJORMINOR, [$GSTPB_REQ], no) dnl GTK is optional and used in examples
GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_MAJORMINOR --variable pluginsdir` HAVE_GTK=NO
AC_SUBST(GSTPB_PLUGINS_DIR) PKG_CHECK_MODULES(GTK2, gtk+-2.0 >= 2.2.0, HAVE_GTK_22=yes, HAVE_GTK_22=no)
AC_MSG_NOTICE(Using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR) 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 dnl set license and copyright notice
GST_LICENSE="LGPL" GST_LICENSE="LGPL"
@ -679,6 +705,7 @@ gst/cdxaparse/Makefile
gst/freeze/Makefile gst/freeze/Makefile
gst/modplug/Makefile gst/modplug/Makefile
gst/modplug/libmodplug/Makefile gst/modplug/libmodplug/Makefile
gst/spectrum/Makefile
gst/speed/Makefile gst/speed/Makefile
gst/qtdemux/Makefile gst/qtdemux/Makefile
gst/tta/Makefile gst/tta/Makefile

View File

@ -4,26 +4,26 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
extern gboolean _gst_plugin_spew; #define DEFAULT_AUDIOSRC "alsasrc"
#define SPECT_BANDS 256
gboolean idle_func (gpointer data);
GtkWidget *drawingarea; GtkWidget *drawingarea;
void static void
spectrum_chain (GstElement * sink, GstBuffer * buf, GstPad * pad, spectrum_chain (GstElement * sink, GstBuffer * buf, GstPad * pad,
gpointer unused) gpointer unused)
{ {
gint i; gint i;
guchar *data = buf->data; 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_window_begin_paint_rect (drawingarea->window, &rect);
gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc, gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc,
TRUE, 0, 0, GST_BUFFER_SIZE (buf), 25); TRUE, 0, 0, width, 50);
for (i = 0; i < GST_BUFFER_SIZE (buf); i++) { for (i = 0; i < width; i++) {
gdk_draw_rectangle (drawingarea->window, drawingarea->style->white_gc, 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); gdk_window_end_paint (drawingarea->window);
} }
@ -32,7 +32,7 @@ int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
GstElement *bin; GstElement *bin;
GstElement *src, *spectrum, *sink; GstElement *src, *conv, *spectrum, *sink;
GtkWidget *appwindow; GtkWidget *appwindow;
@ -42,34 +42,35 @@ main (int argc, char *argv[])
bin = gst_pipeline_new ("bin"); bin = gst_pipeline_new ("bin");
src = gst_element_factory_make (DEFAULT_AUDIOSRC, "src"); 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"); 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"); sink = gst_element_factory_make ("fakesink", "sink");
g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL); g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
g_signal_connect (sink, "handoff", G_CALLBACK (spectrum_chain), NULL); g_signal_connect (sink, "handoff", G_CALLBACK (spectrum_chain), NULL);
gst_bin_add_many (GST_BIN (bin), src, spectrum, sink, NULL); gst_bin_add_many (GST_BIN (bin), src, conv, spectrum, sink, NULL);
gst_element_link_many (src, 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); appwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
drawingarea = gtk_drawing_area_new (); 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_container_add (GTK_CONTAINER (appwindow), drawingarea);
gtk_widget_show_all (appwindow); gtk_widget_show_all (appwindow);
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); gst_element_set_state (bin, GST_STATE_PLAYING);
g_idle_add (idle_func, bin);
gtk_main (); gtk_main ();
gst_element_set_state (bin, GST_STATE_NULL);
gst_object_unref (bin);
return 0; return 0;
} }
gboolean
idle_func (gpointer data)
{
return gst_bin_iterate (data);
}

View File

@ -54,9 +54,6 @@
#define fixed short #define fixed short
/* FIX_MPY() - fixed-point multiplication macro. /* FIX_MPY() - fixed-point multiplication macro.
This macro is a statement, not an expression (uses asm).
BEWARE: make sure _DX is not clobbered by evaluating (A) or DEST.
args are all of type fixed.
Scaling ensures that 32767*32767 = 32767. */ Scaling ensures that 32767*32767 = 32767. */
#define FIX_MPY(DEST,A,B) DEST = ((long)(A) * (long)(B))>>15 #define FIX_MPY(DEST,A,B) DEST = ((long)(A) * (long)(B))>>15
@ -65,8 +62,9 @@
#define LOG2_N_WAVE 10 /* log2(N_WAVE) */ #define LOG2_N_WAVE 10 /* log2(N_WAVE) */
#define N_LOUD 100 /* dimension of Loudampl[] */ #define N_LOUD 100 /* dimension of Loudampl[] */
extern fixed gst_spectrum_Sinewave[N_WAVE]; /* placed at end of this file for clarity */ extern fixed const gst_spectrum_Sinewave[N_WAVE]; /* placed at end of this file for clarity */
extern fixed gst_spectrum_Loudampl[N_LOUD]; extern fixed const gst_spectrum_Loudampl[N_LOUD];
static int gst_spectrum_db_from_ampl (fixed re, fixed im); static int gst_spectrum_db_from_ampl (fixed re, fixed im);
static fixed gst_spectrum_fix_mpy (fixed a, fixed b); static fixed gst_spectrum_fix_mpy (fixed a, fixed b);
@ -221,7 +219,7 @@ gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
/* db_from_ampl() - find loudness (in dB) from /* db_from_ampl() - find loudness (in dB) from
the complex amplitude. the complex amplitude.
*/ */
int static int
gst_spectrum_db_from_ampl (fixed re, fixed im) gst_spectrum_db_from_ampl (fixed re, fixed im)
{ {
static long loud2[N_LOUD] = { 0 }; static long loud2[N_LOUD] = { 0 };
@ -250,17 +248,18 @@ gst_spectrum_db_from_ampl (fixed re, fixed im)
/* /*
fix_mpy() - fixed-point multiplication fix_mpy() - fixed-point multiplication
*/ */
fixed static fixed
gst_spectrum_fix_mpy (fixed a, fixed b) gst_spectrum_fix_mpy (fixed a, fixed b)
{ {
FIX_MPY (a, a, b); FIX_MPY (a, a, b);
return a; return a;
} }
#if 0
/* /*
iscale() - scale an integer value by (numer/denom) iscale() - scale an integer value by (numer/denom)
*/ */
int static int
gst_spectrum_iscale (int value, int numer, int denom) gst_spectrum_iscale (int value, int numer, int denom)
{ {
return (long) value *(long) numer / (long) denom; return (long) value *(long) numer / (long) denom;
@ -269,14 +268,15 @@ gst_spectrum_iscale (int value, int numer, int denom)
/* /*
fix_dot() - dot product of two fixed arrays fix_dot() - dot product of two fixed arrays
*/ */
fixed static fixed
gst_spectrum_fix_dot (fixed * hpa, fixed * pb, int n) gst_spectrum_fix_dot (fixed * hpa, fixed * pb, int n)
{ {
fixed *pa = hpa; /* FIXME */ fixed *pa = hpa; /* FIXME */
long sum; long sum;
register fixed a, b; register fixed a, b;
/* seg = FP_SEG(hpa); /*
seg = FP_SEG(hpa);
off = FP_OFF(hpa); off = FP_OFF(hpa);
seg += off>>4; seg += off>>4;
off &= 0x000F; off &= 0x000F;
@ -298,11 +298,12 @@ gst_spectrum_fix_dot (fixed * hpa, fixed * pb, int n)
return (fixed) sum; return (fixed) sum;
} }
#endif
#if N_WAVE != 1024 #if N_WAVE != 1024
ERROR:N_WAVE != 1024 ERROR:N_WAVE != 1024
#endif #endif
fixed gst_spectrum_Sinewave[1024] = { fixed const gst_spectrum_Sinewave[1024] = {
0, 201, 402, 603, 804, 1005, 1206, 1406, 0, 201, 402, 603, 804, 1005, 1206, 1406,
1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011,
3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608,
@ -431,12 +432,13 @@ ERROR:N_WAVE != 1024
-6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006,
-4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411,
-3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808,
-1607, -1406, -1206, -1005, -804, -603, -402, -201,}; -1607, -1406, -1206, -1005, -804, -603, -402, -201,
};
#if N_LOUD != 100 #if N_LOUD != 100
ERROR:N_LOUD != 100 ERROR:N_LOUD != 100
#endif #endif
fixed gst_spectrum_Loudampl[100] = { fixed const gst_spectrum_Loudampl[100] = {
32767, 29203, 26027, 23197, 20674, 18426, 16422, 14636, 32767, 29203, 26027, 23197, 20674, 18426, 16422, 14636,
13044, 11626, 10361, 9234, 8230, 7335, 6537, 5826, 13044, 11626, 10361, 9234, 8230, 7335, 6537, 5826,
5193, 4628, 4125, 3676, 3276, 2920, 2602, 2319, 5193, 4628, 4125, 3676, 3276, 2920, 2602, 2319,
@ -447,4 +449,5 @@ ERROR:N_LOUD != 100
51, 46, 41, 36, 32, 29, 26, 23, 51, 46, 41, 36, 32, 29, 26, 23,
20, 18, 16, 14, 13, 11, 10, 9, 20, 18, 16, 14, 13, 11, 10, 9,
8, 7, 6, 5, 5, 4, 4, 3, 8, 7, 6, 5, 5, 4, 4, 3,
3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

View File

@ -1,5 +1,6 @@
/* GStreamer /* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -24,12 +25,33 @@
#include "gstspectrum.h" #include "gstspectrum.h"
GST_DEBUG_CATEGORY_STATIC (gst_spectrum_debug);
#define GST_CAT_DEFAULT gst_spectrum_debug
/* elementfactory information */ /* elementfactory information */
static const GstElementDetails gst_spectrum_details = static const GstElementDetails gst_spectrum_details =
GST_ELEMENT_DETAILS ("Spectrum analyzer", GST_ELEMENT_DETAILS ("Spectrum analyzer",
"Filter/Analyzer/Audio", "Filter/Analyzer/Audio",
"Run an FFT on the audio signal, output spectrum data", "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 */ /* Spectrum signals and args */
enum enum
@ -48,18 +70,17 @@ enum
static void gst_spectrum_base_init (gpointer g_class); static void gst_spectrum_base_init (gpointer g_class);
static void gst_spectrum_class_init (GstSpectrumClass * klass); static void gst_spectrum_class_init (GstSpectrumClass * klass);
static void gst_spectrum_init (GstSpectrum * spectrum); 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, static void gst_spectrum_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); 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 #define fixed short
int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse); extern 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 void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
int scale_shift); 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; static GstElementClass *parent_class = NULL;
@ -83,9 +104,10 @@ gst_spectrum_get_type (void)
(GInstanceInitFunc) gst_spectrum_init, (GInstanceInitFunc) gst_spectrum_init,
}; };
spectrum_type = spectrum_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum",
g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum", &spectrum_info, &spectrum_info, 0);
0); GST_DEBUG_CATEGORY_INIT (gst_spectrum_debug, "spectrum", 0,
"audio spectrum analyser element");
} }
return spectrum_type; return spectrum_type;
} }
@ -95,113 +117,128 @@ gst_spectrum_base_init (gpointer g_class)
{ {
GstElementClass *element_class = GST_ELEMENT_CLASS (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); gst_element_class_set_details (element_class, &gst_spectrum_details);
} }
static void static void
gst_spectrum_class_init (GstSpectrumClass * klass) gst_spectrum_class_init (GstSpectrumClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (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->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 static void
gst_spectrum_init (GstSpectrum * spectrum) 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_element_add_pad (GST_ELEMENT (spectrum), spectrum->sinkpad);
gst_pad_set_chain_function (spectrum->sinkpad, gst_spectrum_chain); 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); gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->srcpad);
spectrum->width = 75; 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 static void
gst_spectrum_set_property (GObject * object, guint prop_id, gst_spectrum_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstSpectrum *spectrum; GstSpectrum *spectrum = GST_SPECTRUM (object);
g_return_if_fail (GST_IS_SPECTRUM (object));
spectrum = GST_SPECTRUM (object);
switch (prop_id) { switch (prop_id) {
case ARG_WIDTH: case ARG_WIDTH:
spectrum->width = g_value_get_int (value); spectrum->width = g_value_get_int (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static GstFlowReturn
gst_spectrum_chain (GstPad * pad, GstData * _data) gst_spectrum_chain (GstPad * pad, GstBuffer * buffer)
{ {
GstBuffer *buf = GST_BUFFER (_data);
GstSpectrum *spectrum; GstSpectrum *spectrum;
gint spec_base, spec_len;
gint16 *re, *im, *loud;
gint16 *samples; gint16 *samples;
gint step, pos, i; gint step, pos, num, i;
guchar *spect; guchar *spect;
GstBuffer *newbuf; 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)); spectrum = GST_SPECTRUM (GST_OBJECT_PARENT (pad));
samples = (gint16 *) GST_BUFFER_DATA (buffer);
samples = (gint16 *) GST_BUFFER_DATA (buf); GST_LOG ("buffer-size = %ld", GST_BUFFER_SIZE (buffer));
spec_base = 8; /* FIXME:need a gst_adapter */
spec_len = 1024; num = GST_BUFFER_SIZE (buffer) / 2;
num = MIN (num, spectrum->len);
im = g_malloc (spec_len * sizeof (gint16)); for (i = 0; i < num; i++)
g_return_if_fail (im != NULL); spectrum->re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
loud = g_malloc (spec_len * sizeof (gint16));
g_return_if_fail (loud != NULL);
memset (im, 0, spec_len * sizeof (gint16)); gst_spectrum_window (spectrum->re, spectrum->len);
/*if (spectrum->meta->channels == 2) { */ gst_spectrum_fix_fft (spectrum->re, spectrum->im, spectrum->base, FALSE);
re = g_malloc (spec_len * sizeof (gint16)); gst_spectrum_fix_loud (spectrum->loud, spectrum->re, spectrum->im,
for (i = 0; i < spec_len; i++) spectrum->len, 0);
re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
/*} else */ /* resample to requested width */
/* re = samples; */ step = spectrum->len / (spectrum->width * 4); /* <-- shouldn't this be 2 instead of 4? */
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);
spect = (guchar *) g_malloc (spectrum->width); spect = (guchar *) g_malloc (spectrum->width);
for (i = 0, pos = 0; i < spectrum->width; i++, pos += step) { for (i = 0, pos = 0; i < spectrum->width; i++, pos += step) {
if (loud[pos] > -60) /* > -60 db? */
spect[i] = (loud[pos] + 60) / 2; if (spectrum->loud[pos] > -60) {
else spect[i] = spectrum->loud[pos] + 60;
/*
if (spect[i] > 15);
spect[i] = 15;
*/
} else
/* treat as silence */
spect[i] = 0; spect[i] = 0;
/* if (spect[i] > 15); */
/* spect[i] = 15; */
} }
g_free (loud); gst_buffer_unref (buffer);
gst_buffer_unref (buf);
/* g_free(samples); */
newbuf = gst_buffer_new (); newbuf = gst_buffer_new ();
g_return_if_fail (newbuf != NULL);
GST_BUFFER_DATA (newbuf) = spect; GST_BUFFER_DATA (newbuf) = spect;
GST_BUFFER_SIZE (newbuf) = spectrum->width; GST_BUFFER_SIZE (newbuf) = spectrum->width;
gst_pad_push (spectrum->srcpad, GST_DATA (newbuf)); return gst_pad_push (spectrum->srcpad, newbuf);
} }
static gboolean static gboolean

View File

@ -39,7 +39,7 @@ extern "C" {
#define GST_IS_SPECTRUM(obj) \ #define GST_IS_SPECTRUM(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPECTRUM)) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPECTRUM))
#define GST_IS_SPECTRUM_CLASS(obj) \ #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 _GstSpectrum GstSpectrum;
typedef struct _GstSpectrumClass GstSpectrumClass; typedef struct _GstSpectrumClass GstSpectrumClass;
@ -50,6 +50,8 @@ struct _GstSpectrum {
GstPad *sinkpad,*srcpad; GstPad *sinkpad,*srcpad;
gint width; gint width;
gint base, len;
gint16 *re, *im, *loud;
}; };
struct _GstSpectrumClass { struct _GstSpectrumClass {