From 83b3960a08bd99ccff51a8f3f65c4a0ac777713c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Sat, 20 May 2006 22:42:15 +0000 Subject: 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 --- gst/spectrum/gstspectrum.c | 167 +++++++++++++++++++++++++++------------------ gst/spectrum/gstspectrum.h | 4 +- 2 files changed, 105 insertions(+), 66 deletions(-) (limited to 'gst/spectrum') diff --git a/gst/spectrum/gstspectrum.c b/gst/spectrum/gstspectrum.c index 4f01ceff..12762c58 100644 --- a/gst/spectrum/gstspectrum.c +++ b/gst/spectrum/gstspectrum.c @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen + * <2006> Stefan Kost * * 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 "); + "Erik Walthinsen ," + "Stefan Kost "); + +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 diff --git a/gst/spectrum/gstspectrum.h b/gst/spectrum/gstspectrum.h index 8cc546ec..2dbc2242 100644 --- a/gst/spectrum/gstspectrum.h +++ b/gst/spectrum/gstspectrum.h @@ -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 { -- cgit