Commit f5a3e61e authored by Sebastian Dröge's avatar Sebastian Dröge 🍵
Browse files

Port GstSpectrum to GstAudioFilter and libgstfft, add support for int32, float...

Port GstSpectrum to GstAudioFilter and libgstfft, add support for int32, float and double, use floats for the message...

Original commit message from CVS:
* configure.ac:
* gst/spectrum/Makefile.am:
* gst/spectrum/demo-audiotest.c: (draw_spectrum),
(message_handler), (main):
* gst/spectrum/demo-osssrc.c: (draw_spectrum), (message_handler):
* gst/spectrum/gstspectrum.c: (gst_spectrum_base_init),
(gst_spectrum_class_init), (gst_spectrum_init),
(gst_spectrum_dispose), (gst_spectrum_set_property),
(gst_spectrum_get_property), (gst_spectrum_start),
(gst_spectrum_setup), (gst_spectrum_message_new),
(gst_spectrum_transform_ip):
* gst/spectrum/gstspectrum.h:
Port GstSpectrum to GstAudioFilter and libgstfft, add support
for int32, float and double, use floats for the message contents,
average all FFTs done in one interval for better results, use
a better windowing function, allow posting the phase in the message
and actually do an FFT with the requested number of bands instead
of interpolating.
* tests/check/elements/spectrum.c: (GST_START_TEST),
(spectrum_suite):
Improve the units tests by checking for a 11025Hz sine wave
and add unit tests for all 4 supported sample types.
parent c8af2199
plugin_LTLIBRARIES = libgstspectrum.la
libgstspectrum_la_SOURCES = gstspectrum.c fix_fft.c
libgstspectrum_la_SOURCES = gstspectrum.c
libgstspectrum_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_CFLAGS)
libgstspectrum_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS)
libgstspectrum_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) -lgstaudio-$(GST_MAJORMINOR) -lgstfft-$(GST_MAJORMINOR) $(LIBM)
libgstspectrum_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstspectrum.h
......
This diff is collapsed.
......@@ -25,6 +25,7 @@
#include <gst/gst.h>
#include <gst/base/gstadapter.h>
#include <gst/base/gstbasetransform.h>
#include <gst/audio/gstaudiofilter.h>
#ifdef __cplusplus
extern "C" {
......@@ -39,9 +40,11 @@ extern "C" {
typedef struct _GstSpectrum GstSpectrum;
typedef struct _GstSpectrumClass GstSpectrumClass;
typedef void (*GstSpectrumProcessFunc) (GstSpectrum *, const guint8 *);
typedef void (*GstSpectrumFFTFreeFunc) (void *);
struct _GstSpectrum {
GstBaseTransform element;
GstAudioFilter element;
GstPad *sinkpad,*srcpad;
GstAdapter *adapter;
......@@ -49,24 +52,28 @@ struct _GstSpectrum {
/* properties */
gboolean message; /* whether or not to post messages */
gboolean message_magnitude;
gboolean message_phase;
guint64 interval; /* how many seconds between emits */
guint bands; /* number of spectrum bands */
gint threshold; /* energy level treshold */
gint num_frames; /* frame count (1 sample per channel)
* since last emit */
gint num_fft; /* number of FFTs since last emit */
gint rate; /* caps variables */
gint channels;
/* <private> */
gint base, len;
gint16 *re, *im, *loud;
guchar *spect;
gfloat *spect_magnitude;
gfloat *spect_phase;
GstSpectrumProcessFunc process;
void *fft_ctx;
GstSpectrumFFTFreeFunc fft_free_func;
void *in;
void *freqdata;
};
struct _GstSpectrumClass {
GstBaseTransformClass parent_class;
GstAudioFilterClass parent_class;
};
GType gst_spectrum_get_type (void);
......
......@@ -33,24 +33,59 @@ gboolean have_eos = FALSE;
GstPad *mysrcpad, *mysinkpad;
#define SPECT_CAPS_TEMPLATE_STRING \
"audio/x-raw-int, " \
" width = (int) 16, " \
" depth = (int) 16, " \
" signed = (boolean) true, " \
" endianness = (int) BYTE_ORDER, " \
" rate = (int) [ 1, MAX ], " \
" channels = (int) [ 1, MAX ]; " \
"audio/x-raw-int, " \
" width = (int) 32, " \
" depth = (int) 32, " \
" signed = (boolean) true, " \
" endianness = (int) BYTE_ORDER, " \
" rate = (int) [ 1, MAX ], " \
" channels = (int) [ 1, MAX ]; " \
"audio/x-raw-float, " \
" width = (int) { 32, 64 }, " \
" endianness = (int) BYTE_ORDER, " \
" rate = (int) [ 1, MAX ], " \
" channels = (int) [ 1, MAX ]"
#define SPECT_CAPS_STRING_S16 \
"audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 8 ], " \
"rate = (int) 44100, " \
"channels = (int) 1, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) {8, 16}, " \
"depth = (int) {8, 16}, " \
"width = (int) 16, " \
"depth = (int) 16, " \
"signed = (boolean) true"
#define SPECT_CAPS_STRING \
#define SPECT_CAPS_STRING_S32 \
"audio/x-raw-int, " \
"rate = (int) 44100, " \
"channels = (int) 1, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 16, " \
"depth = (int) 16, " \
"width = (int) 32, " \
"depth = (int) 32, " \
"signed = (boolean) true"
#define SPECT_BANDS 64
#define SPECT_CAPS_STRING_F32 \
"audio/x-raw-float, " \
" width = (int) 32, " \
" endianness = (int) BYTE_ORDER, " \
" rate = (int) 44100, " \
" channels = (int) 1"
#define SPECT_CAPS_STRING_F64 \
"audio/x-raw-float, " \
" width = (int) 64, " \
" endianness = (int) BYTE_ORDER, " \
" rate = (int) 44100, " \
" channels = (int) 1"
#define SPECT_BANDS 256
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
......@@ -104,24 +139,338 @@ GST_START_TEST (test_int16)
gint16 *data;
const GValue *list, *value;
GstClockTime endtime;
guchar level;
gfloat level;
spectrum = setup_spectrum ();
g_object_set (spectrum, "message", TRUE, "interval", GST_SECOND / 10,
g_object_set (spectrum, "message", TRUE, "interval", GST_SECOND / 100,
"bands", SPECT_BANDS, "threshold", -80, NULL);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
/* create a fake 1 sec buffer with a half-amplitude block signal */
/* create a 1 sec buffer with an 11025 Hz sine wave */
inbuffer = gst_buffer_new_and_alloc (44100 * sizeof (gint16));
data = (gint16 *) GST_BUFFER_DATA (inbuffer);
for (j = 0; j < 44100; ++j) {
*data = 16536;
for (j = 0; j < 44100; j += 4) {
*data = 0;
++data;
*data = 32767;
++data;
*data = 0;
++data;
*data = -32767;
++data;
}
caps = gst_caps_from_string (SPECT_CAPS_STRING_S16);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* create a bus to get the spectrum message on */
bus = gst_bus_new ();
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_element_set_bus (spectrum, bus);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
ASSERT_OBJECT_REFCOUNT (message, "message", 1);
fail_unless (message != NULL);
fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
structure = gst_message_get_structure (message);
fail_if (structure == NULL);
fail_unless_equals_string ((char *) gst_structure_get_name (structure),
"spectrum");
fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
list = gst_structure_get_value (structure, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
level = g_value_get_float (value);
GST_DEBUG ("band[%3d] is %.2f", i, level);
/* Only the bands in the middle should have a level above 60 */
fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
&& level < 60.0);
fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
&& level > 60.0);
}
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
/* clean up */
/* flush current messages,and future state change messages */
gst_bus_set_flushing (bus, TRUE);
/* message has a ref to the element */
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
gst_message_unref (message);
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
gst_element_set_bus (spectrum, NULL);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_object_unref (bus);
gst_buffer_unref (outbuffer);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
cleanup_spectrum (spectrum);
}
GST_END_TEST;
GST_START_TEST (test_int32)
{
GstElement *spectrum;
GstBuffer *inbuffer, *outbuffer;
GstBus *bus;
GstCaps *caps;
GstMessage *message;
const GstStructure *structure;
int i, j;
gint32 *data;
const GValue *list, *value;
GstClockTime endtime;
gfloat level;
spectrum = setup_spectrum ();
g_object_set (spectrum, "message", TRUE, "interval", GST_SECOND / 100,
"bands", SPECT_BANDS, "threshold", -80, NULL);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
/* create a 1 sec buffer with an 11025 Hz sine wave */
inbuffer = gst_buffer_new_and_alloc (44100 * sizeof (gint32));
data = (gint32 *) GST_BUFFER_DATA (inbuffer);
for (j = 0; j < 44100; j += 4) {
*data = 0;
++data;
*data = 2147483647;
++data;
*data = 0;
++data;
*data = -2147483647;
++data;
}
caps = gst_caps_from_string (SPECT_CAPS_STRING_S32);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* create a bus to get the spectrum message on */
bus = gst_bus_new ();
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_element_set_bus (spectrum, bus);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
ASSERT_OBJECT_REFCOUNT (message, "message", 1);
fail_unless (message != NULL);
fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
structure = gst_message_get_structure (message);
fail_if (structure == NULL);
fail_unless_equals_string ((char *) gst_structure_get_name (structure),
"spectrum");
fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
list = gst_structure_get_value (structure, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
level = g_value_get_float (value);
GST_DEBUG ("band[%3d] is %.2f", i, level);
/* Only the bands in the middle should have a level above 60 */
fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
&& level < 60.0);
fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
&& level > 60.0);
}
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
/* clean up */
/* flush current messages,and future state change messages */
gst_bus_set_flushing (bus, TRUE);
/* message has a ref to the element */
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
gst_message_unref (message);
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
gst_element_set_bus (spectrum, NULL);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_object_unref (bus);
gst_buffer_unref (outbuffer);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
cleanup_spectrum (spectrum);
}
GST_END_TEST;
GST_START_TEST (test_float32)
{
GstElement *spectrum;
GstBuffer *inbuffer, *outbuffer;
GstBus *bus;
GstCaps *caps;
GstMessage *message;
const GstStructure *structure;
int i, j;
gfloat *data;
const GValue *list, *value;
GstClockTime endtime;
gfloat level;
spectrum = setup_spectrum ();
g_object_set (spectrum, "message", TRUE, "interval", GST_SECOND / 100,
"bands", SPECT_BANDS, "threshold", -80, NULL);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
/* create a 1 sec buffer with an 11025 Hz sine wave */
inbuffer = gst_buffer_new_and_alloc (44100 * sizeof (gfloat));
data = (gfloat *) GST_BUFFER_DATA (inbuffer);
for (j = 0; j < 44100; j += 4) {
*data = 0.0;
++data;
*data = 1.0;
++data;
*data = 0.0;
++data;
*data = -1.0;
++data;
}
caps = gst_caps_from_string (SPECT_CAPS_STRING_F32);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* create a bus to get the spectrum message on */
bus = gst_bus_new ();
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_element_set_bus (spectrum, bus);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
ASSERT_OBJECT_REFCOUNT (message, "message", 1);
fail_unless (message != NULL);
fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (spectrum));
fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
structure = gst_message_get_structure (message);
fail_if (structure == NULL);
fail_unless_equals_string ((char *) gst_structure_get_name (structure),
"spectrum");
fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
list = gst_structure_get_value (structure, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
level = g_value_get_float (value);
GST_DEBUG ("band[%3d] is %.2f", i, level);
/* Only the bands in the middle should have a level above 60 */
fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
&& level < 60.0);
fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
&& level > 60.0);
}
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
/* clean up */
/* flush current messages,and future state change messages */
gst_bus_set_flushing (bus, TRUE);
/* message has a ref to the element */
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 2);
gst_message_unref (message);
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
gst_element_set_bus (spectrum, NULL);
ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
gst_object_unref (bus);
gst_buffer_unref (outbuffer);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
ASSERT_OBJECT_REFCOUNT (spectrum, "spectrum", 1);
cleanup_spectrum (spectrum);
}
GST_END_TEST;
GST_START_TEST (test_float64)
{
GstElement *spectrum;
GstBuffer *inbuffer, *outbuffer;
GstBus *bus;
GstCaps *caps;
GstMessage *message;
const GstStructure *structure;
int i, j;
gdouble *data;
const GValue *list, *value;
GstClockTime endtime;
gfloat level;
spectrum = setup_spectrum ();
g_object_set (spectrum, "message", TRUE, "interval", GST_SECOND / 100,
"bands", SPECT_BANDS, "threshold", -80, NULL);
fail_unless (gst_element_set_state (spectrum,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
/* create a 1 sec buffer with an 11025 Hz sine wave */
inbuffer = gst_buffer_new_and_alloc (44100 * sizeof (gdouble));
data = (gdouble *) GST_BUFFER_DATA (inbuffer);
for (j = 0; j < 44100; j += 4) {
*data = 0.0;
++data;
*data = 1.0;
++data;
*data = 0.0;
++data;
*data = -1.0;
++data;
}
caps = gst_caps_from_string (SPECT_CAPS_STRING);
caps = gst_caps_from_string (SPECT_CAPS_STRING_F64);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
......@@ -152,13 +501,16 @@ GST_START_TEST (test_int16)
"spectrum");
fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
/* block wave of half amplitude has -5.94 dB for rms, peak and decay */
list = gst_structure_get_value (structure, "spectrum");
list = gst_structure_get_value (structure, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
level = g_value_get_uchar (value);
GST_DEBUG ("band[%3d] is %3d", i, level);
fail_if (level == 0);
level = g_value_get_float (value);
GST_DEBUG ("band[%3d] is %.2f", i, level);
/* Only the bands in the middle should have a level above 60 */
fail_if ((i == SPECT_BANDS / 2 || i == SPECT_BANDS / 2 - 1)
&& level < 60.0);
fail_if ((i != SPECT_BANDS / 2 && i != SPECT_BANDS / 2 - 1)
&& level > 60.0);
}
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
......@@ -194,6 +546,9 @@ spectrum_suite (void)
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_int16);
tcase_add_test (tc_chain, test_int32);
tcase_add_test (tc_chain, test_float32);
tcase_add_test (tc_chain, test_float64);
return s;
}
......
......@@ -51,7 +51,7 @@ on_frequency_changed (GtkRange * range, gpointer user_data)
/* draw frequency spectrum as a bunch of bars */
static void
draw_spectrum (guchar * data)
draw_spectrum (gfloat * data)
{
gint i;
GdkRectangle rect = { 0, 0, SPECT_BANDS, 50 };
......@@ -78,15 +78,15 @@ message_handler (GstBus * bus, GstMessage * message, gpointer data)
const gchar *name = gst_structure_get_name (s);
if (strcmp (name, "spectrum") == 0) {
guchar spect[SPECT_BANDS];
gfloat spect[SPECT_BANDS];
const GValue *list;
const GValue *value;
guint i;
list = gst_structure_get_value (s, "spectrum");
list = gst_structure_get_value (s, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
spect[i] = g_value_get_uchar (value);
spect[i] = g_value_get_float (value);
}
draw_spectrum (spect);
}
......@@ -98,7 +98,7 @@ int
main (int argc, char *argv[])
{
GstElement *bin;
GstElement *src, *spectrum, *sink;
GstElement *src, *spectrum, *audioconvert, *sink;
GstBus *bus;
GtkWidget *appwindow, *vbox, *widget;
......@@ -116,10 +116,12 @@ main (int argc, char *argv[])
g_object_set (G_OBJECT (spectrum), "bands", SPECT_BANDS, "threshold", -80,
"message", TRUE, NULL);
audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
sink = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink");
gst_bin_add_many (GST_BIN (bin), src, spectrum, sink, NULL);
if (!gst_element_link_many (src, spectrum, sink, NULL)) {
gst_bin_add_many (GST_BIN (bin), src, spectrum, audioconvert, sink, NULL);
if (!gst_element_link_many (src, spectrum, audioconvert, sink, NULL)) {
fprintf (stderr, "cant link elements\n");
exit (1);
}
......
......@@ -43,7 +43,7 @@ on_window_destroy (GtkObject * object, gpointer user_data)
/* draw frequency spectrum as a bunch of bars */
static void
draw_spectrum (guchar * data)
draw_spectrum (gfloat * data)
{
gint i;
GdkRectangle rect = { 0, 0, SPECT_WIDTH, SPECT_HEIGHT };
......@@ -70,15 +70,15 @@ message_handler (GstBus * bus, GstMessage * message, gpointer data)
const gchar *name = gst_structure_get_name (s);
if (strcmp (name, "spectrum") == 0) {
guchar spect[SPECT_BANDS];
gfloat spect[SPECT_BANDS];
const GValue *list;
const GValue *value;
guint i;
list = gst_structure_get_value (s, "spectrum");
list = gst_structure_get_value (s, "magnitude");
for (i = 0; i < SPECT_BANDS; ++i) {
value = gst_value_list_get_value (list, i);
spect[i] = g_value_get_uchar (value);
spect[i] = g_value_get_float (value);
}
draw_spectrum (spect);
}
......
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