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:
parent
4e5f3fae24
commit
0428d5cf5f
12
ChangeLog
12
ChangeLog
@ -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:
|
||||||
|
35
configure.ac
35
configure.ac
@ -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
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
@ -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,
|
||||||
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user