summaryrefslogtreecommitdiff
path: root/gst/spectrum/gstspectrum.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/spectrum/gstspectrum.c')
-rw-r--r--gst/spectrum/gstspectrum.c291
1 files changed, 70 insertions, 221 deletions
diff --git a/gst/spectrum/gstspectrum.c b/gst/spectrum/gstspectrum.c
index 4d7250b0f..e9bd8a5ce 100644
--- a/gst/spectrum/gstspectrum.c
+++ b/gst/spectrum/gstspectrum.c
@@ -110,38 +110,17 @@ GST_DEBUG_CATEGORY_STATIC (gst_spectrum_debug);
#define GST_CAT_DEFAULT gst_spectrum_debug
/* elementfactory information */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+# define FORMATS "{ S16LE, S24LE, S32LE, F32LE, F64LE }"
+#else
+# define FORMATS "{ S16BE, S24BE, S32BE, F32BE, F64BE }"
+#endif
#define ALLOWED_CAPS \
- "audio/x-raw-int, " \
- " width = (int) 16, " \
- " depth = (int) [ 1, 16 ], " \
- " signed = (boolean) true, " \
- " endianness = (int) BYTE_ORDER, " \
- " rate = (int) [ 1, MAX ], " \
- " channels = (int) [ 1, MAX ]; " \
- "audio/x-raw-int, " \
- " width = (int) 24, " \
- " depth = (int) [ 1, 24 ], " \
- " signed = (boolean) true, " \
- " endianness = (int) BYTE_ORDER, " \
- " rate = (int) [ 1, MAX ], " \
- " channels = (int) [ 1, MAX ]; " \
- "audio/x-raw-int, " \
- " width = (int) 32, " \
- " depth = (int) [ 1, 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 ]"
+ GST_AUDIO_CAPS_MAKE (FORMATS)
/* Spectrum properties */
-#define DEFAULT_MESSAGE TRUE
-#define DEFAULT_POST_MESSAGES TRUE
+#define DEFAULT_POST_MESSAGES TRUE
#define DEFAULT_MESSAGE_MAGNITUDE TRUE
#define DEFAULT_MESSAGE_PHASE FALSE
#define DEFAULT_INTERVAL (GST_SECOND / 10)
@@ -152,7 +131,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_spectrum_debug);
enum
{
PROP_0,
- PROP_MESSAGE,
PROP_POST_MESSAGES,
PROP_MESSAGE_MAGNITUDE,
PROP_MESSAGE_PHASE,
@@ -162,8 +140,8 @@ enum
PROP_MULTI_CHANNEL
};
-GST_BOILERPLATE (GstSpectrum, gst_spectrum, GstAudioFilter,
- GST_TYPE_AUDIO_FILTER);
+#define gst_spectrum_parent_class parent_class
+G_DEFINE_TYPE (GstSpectrum, gst_spectrum, GST_TYPE_AUDIO_FILTER);
static void gst_spectrum_finalize (GObject * object);
static void gst_spectrum_set_property (GObject * object, guint prop_id,
@@ -175,33 +153,16 @@ static gboolean gst_spectrum_stop (GstBaseTransform * trans);
static GstFlowReturn gst_spectrum_transform_ip (GstBaseTransform * trans,
GstBuffer * in);
static gboolean gst_spectrum_setup (GstAudioFilter * base,
- GstRingBufferSpec * format);
-
-static void
-gst_spectrum_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- GstCaps *caps;
-
- gst_element_class_set_details_simple (element_class, "Spectrum analyzer",
- "Filter/Analyzer/Audio",
- "Run an FFT on the audio signal, output spectrum data",
- "Erik Walthinsen <omega@cse.ogi.edu>, "
- "Stefan Kost <ensonic@users.sf.net>, "
- "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-
- caps = gst_caps_from_string (ALLOWED_CAPS);
- gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (g_class),
- caps);
- gst_caps_unref (caps);
-}
+ const GstAudioInfo * info);
static void
gst_spectrum_class_init (GstSpectrumClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (klass);
+ GstCaps *caps;
gobject_class->set_property = gst_spectrum_set_property;
gobject_class->get_property = gst_spectrum_get_property;
@@ -214,12 +175,6 @@ gst_spectrum_class_init (GstSpectrumClass * klass)
filter_class->setup = GST_DEBUG_FUNCPTR (gst_spectrum_setup);
- /* FIXME 0.11, remove in favour of post-messages */
- g_object_class_install_property (gobject_class, PROP_MESSAGE,
- g_param_spec_boolean ("message", "Message",
- "Whether to post a 'spectrum' element message on the bus for each "
- "passed interval (deprecated, use post-messages)", DEFAULT_MESSAGE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstSpectrum:post-messages
*
@@ -277,10 +232,21 @@ gst_spectrum_class_init (GstSpectrumClass * klass)
GST_DEBUG_CATEGORY_INIT (gst_spectrum_debug, "spectrum", 0,
"audio spectrum analyser element");
+
+ gst_element_class_set_details_simple (element_class, "Spectrum analyzer",
+ "Filter/Analyzer/Audio",
+ "Run an FFT on the audio signal, output spectrum data",
+ "Erik Walthinsen <omega@cse.ogi.edu>, "
+ "Stefan Kost <ensonic@users.sf.net>, "
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ caps = gst_caps_from_string (ALLOWED_CAPS);
+ gst_audio_filter_class_add_pad_templates (filter_class, caps);
+ gst_caps_unref (caps);
}
static void
-gst_spectrum_init (GstSpectrum * spectrum, GstSpectrumClass * g_class)
+gst_spectrum_init (GstSpectrum * spectrum)
{
spectrum->post_messages = DEFAULT_POST_MESSAGES;
spectrum->message_magnitude = DEFAULT_MESSAGE_MAGNITUDE;
@@ -301,7 +267,7 @@ gst_spectrum_alloc_channel_data (GstSpectrum * spectrum)
g_assert (spectrum->channel_data == NULL);
spectrum->num_channels = (spectrum->multi_channel) ?
- GST_AUDIO_FILTER (spectrum)->format.channels : 1;
+ GST_AUDIO_FILTER_CHANNELS (spectrum) : 1;
GST_DEBUG_OBJECT (spectrum, "allocating data for %d channels",
spectrum->num_channels);
@@ -378,7 +344,6 @@ gst_spectrum_set_property (GObject * object, guint prop_id,
GstSpectrum *filter = GST_SPECTRUM (object);
switch (prop_id) {
- case PROP_MESSAGE:
case PROP_POST_MESSAGES:
filter->post_messages = g_value_get_boolean (value);
break;
@@ -434,7 +399,6 @@ gst_spectrum_get_property (GObject * object, guint prop_id,
GstSpectrum *filter = GST_SPECTRUM (object);
switch (prop_id) {
- case PROP_MESSAGE:
case PROP_POST_MESSAGES:
g_value_set_boolean (value, filter->post_messages);
break;
@@ -519,23 +483,6 @@ input_data_mixed_double (const guint8 * _in, gfloat * out, guint len,
}
static void
-input_data_mixed_int32 (const guint8 * _in, gfloat * out, guint len,
- guint channels, gfloat max_value, guint op, guint nfft)
-{
- guint i, j, ip = 0;
- gint32 *in = (gint32 *) _in;
- gfloat v;
-
- for (j = 0; j < len; j++) {
- v = in[ip++] * 2 + 1;
- for (i = 1; i < channels; i++)
- v += in[ip++] * 2 + 1;
- out[op] = v / channels;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_mixed_int32_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -553,30 +500,6 @@ input_data_mixed_int32_max (const guint8 * _in, gfloat * out, guint len,
}
static void
-input_data_mixed_int24 (const guint8 * _in, gfloat * out, guint len,
- guint channels, gfloat max_value, guint op, guint nfft)
-{
- guint i, j;
- gfloat v = 0.0;
-
- for (j = 0; j < len; j++) {
- for (i = 0; i < channels; i++) {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- gint32 value = GST_READ_UINT24_BE (_in);
-#else
- gint32 value = GST_READ_UINT24_LE (_in);
-#endif
- if (value & 0x00800000)
- value |= 0xff000000;
- v += value * 2 + 1;
- _in += 3;
- }
- out[op] = v / channels;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_mixed_int24_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -601,23 +524,6 @@ input_data_mixed_int24_max (const guint8 * _in, gfloat * out, guint len,
}
static void
-input_data_mixed_int16 (const guint8 * _in, gfloat * out, guint len,
- guint channels, gfloat max_value, guint op, guint nfft)
-{
- guint i, j, ip = 0;
- gint16 *in = (gint16 *) _in;
- gfloat v;
-
- for (j = 0; j < len; j++) {
- v = in[ip++] * 2 + 1;
- for (i = 1; i < channels; i++)
- v += in[ip++] * 2 + 1;
- out[op] = v / channels;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_mixed_int16_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -663,19 +569,6 @@ input_data_double (const guint8 * _in, gfloat * out, guint len, guint channels,
}
static void
-input_data_int32 (const guint8 * _in, gfloat * out, guint len, guint channels,
- gfloat max_value, guint op, guint nfft)
-{
- guint j, ip;
- gint32 *in = (gint32 *) _in;
-
- for (j = 0, ip = 0; j < len; j++, ip += channels) {
- out[op] = in[ip] * 2 + 1;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_int32_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -689,26 +582,6 @@ input_data_int32_max (const guint8 * _in, gfloat * out, guint len,
}
static void
-input_data_int24 (const guint8 * _in, gfloat * out, guint len, guint channels,
- gfloat max_value, guint op, guint nfft)
-{
- guint j;
-
- for (j = 0; j < len; j++) {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- gint32 v = GST_READ_UINT24_BE (_in);
-#else
- gint32 v = GST_READ_UINT24_LE (_in);
-#endif
- if (v & 0x00800000)
- v |= 0xff000000;
- _in += 3 * channels;
- out[op] = v * 2 + 1;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_int24_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -729,19 +602,6 @@ input_data_int24_max (const guint8 * _in, gfloat * out, guint len,
}
static void
-input_data_int16 (const guint8 * _in, gfloat * out, guint len, guint channels,
- gfloat max_value, guint op, guint nfft)
-{
- guint j, ip;
- gint16 *in = (gint16 *) _in;
-
- for (j = 0, ip = 0; j < len; j++, ip += channels) {
- out[op] = in[ip] * 2 + 1;
- op = (op + 1) % nfft;
- }
-}
-
-static void
input_data_int16_max (const guint8 * _in, gfloat * out, guint len,
guint channels, gfloat max_value, guint op, guint nfft)
{
@@ -755,54 +615,39 @@ input_data_int16_max (const guint8 * _in, gfloat * out, guint len,
}
static gboolean
-gst_spectrum_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+gst_spectrum_setup (GstAudioFilter * base, const GstAudioInfo * info)
{
GstSpectrum *spectrum = GST_SPECTRUM (base);
- guint width = format->width / 8;
- gboolean is_float = (format->type == GST_BUFTYPE_FLOAT);
- /* max_value will be 0 when depth is 1,
- * interpret -1 and 0 as -1 and +1 if that's the case. */
- guint max_value = (1UL << (format->depth - 1)) - 1;
gboolean multi_channel = spectrum->multi_channel;
GstSpectrumInputData input_data = NULL;
- if (is_float) {
- if (width == 4) {
+ switch (GST_AUDIO_INFO_FORMAT (info)) {
+ case GST_AUDIO_FORMAT_S16:
+ input_data =
+ multi_channel ? input_data_int16_max : input_data_mixed_int16_max;
+ break;
+ case GST_AUDIO_FORMAT_S24:
+ input_data =
+ multi_channel ? input_data_int24_max : input_data_mixed_int24_max;
+ break;
+ case GST_AUDIO_FORMAT_S32:
+ input_data =
+ multi_channel ? input_data_int32_max : input_data_mixed_int32_max;
+ break;
+ case GST_AUDIO_FORMAT_F32:
input_data = multi_channel ? input_data_float : input_data_mixed_float;
- } else if (width == 8) {
+ break;
+ case GST_AUDIO_FORMAT_F64:
input_data = multi_channel ? input_data_double : input_data_mixed_double;
- } else {
- g_assert_not_reached ();
- }
- } else {
- if (width == 4) {
- if (max_value) {
- input_data =
- multi_channel ? input_data_int32_max : input_data_mixed_int32_max;
- } else {
- input_data = multi_channel ? input_data_int32 : input_data_mixed_int32;
- }
- } else if (width == 3) {
- if (max_value) {
- input_data =
- multi_channel ? input_data_int24_max : input_data_mixed_int24_max;
- } else {
- input_data = multi_channel ? input_data_int24 : input_data_mixed_int24;
- }
- } else if (width == 2) {
- if (max_value) {
- input_data =
- multi_channel ? input_data_int16_max : input_data_mixed_int16_max;
- } else {
- input_data = multi_channel ? input_data_int16 : input_data_mixed_int16;
- }
- } else {
+ break;
+ default:
g_assert_not_reached ();
- }
+ break;
}
-
spectrum->input_data = input_data;
+
gst_spectrum_reset_state (spectrum);
+
return TRUE;
}
@@ -894,7 +739,7 @@ gst_spectrum_message_new (GstSpectrum * spectrum, GstClockTime timestamp,
}
} else {
guint c;
- guint channels = GST_AUDIO_FILTER (spectrum)->format.channels;
+ guint channels = GST_AUDIO_FILTER_CHANNELS (spectrum);
if (spectrum->message_magnitude) {
mcv = gst_spectrum_message_add_container (s, GST_TYPE_ARRAY, "magnitude");
@@ -1000,26 +845,27 @@ static GstFlowReturn
gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
{
GstSpectrum *spectrum = GST_SPECTRUM (trans);
- GstRingBufferSpec *format = &GST_AUDIO_FILTER (spectrum)->format;
- guint rate = format->rate;
- guint channels = format->channels;
+ guint rate = GST_AUDIO_FILTER_RATE (spectrum);
+ guint channels = GST_AUDIO_FILTER_CHANNELS (spectrum);
+ guint bps = GST_AUDIO_FILTER_BPS (spectrum);
+ guint bpf = GST_AUDIO_FILTER_BPF (spectrum);
guint output_channels = spectrum->multi_channel ? channels : 1;
guint c;
- guint width = format->width / 8;
- gfloat max_value = (1UL << (format->depth - 1)) - 1;
+ gfloat max_value = (1UL << ((bps << 3) - 1)) - 1;
guint bands = spectrum->bands;
guint nfft = 2 * bands - 2;
guint input_pos;
gfloat *input;
- const guint8 *data = GST_BUFFER_DATA (buffer);
- guint size = GST_BUFFER_SIZE (buffer);
- guint frame_size = width * channels;
+ const guint8 *data, *mdata;
+ gsize size;
guint fft_todo, msg_todo, block_size;
gboolean have_full_interval;
GstSpectrumChannel *cd;
GstSpectrumInputData input_data;
- GST_LOG_OBJECT (spectrum, "input size: %d bytes", GST_BUFFER_SIZE (buffer));
+ data = mdata = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+
+ GST_LOG_OBJECT (spectrum, "input size: %" G_GSIZE_FORMAT " bytes", size);
if (GST_BUFFER_IS_DISCONT (buffer)) {
GST_DEBUG_OBJECT (spectrum, "Discontinuity detected -- flushing");
@@ -1061,16 +907,16 @@ gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
input_pos = spectrum->input_pos;
input_data = spectrum->input_data;
- while (size >= frame_size) {
+ while (size >= bpf) {
/* run input_data for a chunk of data */
fft_todo = nfft - (spectrum->num_frames % nfft);
msg_todo = spectrum->frames_todo - spectrum->num_frames;
GST_LOG_OBJECT (spectrum,
- "message frames todo: %u, fft frames todo: %u, input frames %u",
- msg_todo, fft_todo, (size / frame_size));
+ "message frames todo: %u, fft frames todo: %u, input frames %"
+ G_GSIZE_FORMAT, msg_todo, fft_todo, (size / bpf));
block_size = msg_todo;
- if (block_size > (size / frame_size))
- block_size = (size / frame_size);
+ if (block_size > (size / bpf))
+ block_size = (size / bpf);
if (block_size > fft_todo)
block_size = fft_todo;
@@ -1078,17 +924,18 @@ gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
cd = &spectrum->channel_data[c];
input = cd->input;
/* Move the current frames into our ringbuffers */
- input_data (data + c * width, input, block_size, channels, max_value,
+ input_data (data + c * bps, input, block_size, channels, max_value,
input_pos, nfft);
}
- data += block_size * frame_size;
- size -= block_size * frame_size;
+ data += block_size * bpf;
+ size -= block_size * bpf;
input_pos = (input_pos + block_size) % nfft;
spectrum->num_frames += block_size;
have_full_interval = (spectrum->num_frames == spectrum->frames_todo);
- GST_LOG_OBJECT (spectrum, "size: %u, do-fft = %d, do-message = %d", size,
+ GST_LOG_OBJECT (spectrum,
+ "size: %" G_GSIZE_FORMAT ", do-fft = %d, do-message = %d", size,
(spectrum->num_frames % nfft == 0), have_full_interval);
/* If we have enough frames for an FFT or we have all frames required for
@@ -1145,6 +992,8 @@ gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
spectrum->input_pos = input_pos;
+ gst_buffer_unmap (buffer, (guint8 *) mdata, -1);
+
g_assert (size == 0);
return GST_FLOW_OK;