*/
/**
- * SECTION:element-plugin
+ * SECTION:element-aubiotempo
*
* <refsect2>
+ * Detects beats along an audio stream
* <title>Example launch line</title>
* <para>
* <programlisting>
- * gst-launch -v -m audiotestsrc ! plugin ! fakesink silent=TRUE
+ * gst-launch -v -m audiotestsrc ! aubiotempo ! fakesink silent=TRUE
* </programlisting>
* </para>
* </refsect2>
# include <config.h>
#endif
+#include <aubio/aubio.h>
+
#include <gst/gst.h>
+#include <gst/audio/audio.h>
#include "gstaubiotempo.h"
-GST_DEBUG_CATEGORY_STATIC (gst_aubiotempo_debug);
#define GST_CAT_DEFAULT gst_aubiotempo_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("Aubio Tempo Analysis",
+ "Filter/Analyzer/Audio",
+ "Extract tempo period and beat locations using aubio",
+ "Paul Brossier <piem@aubio.org>");
/* Filter signals and args */
enum
enum
{
- ARG_0,
- ARG_SILENT
+ PROP_0,
+ PROP_SILENT
};
+#define ALLOWED_CAPS \
+ "audio/x-raw-float," \
+ " width=(int)32," \
+ " endianness=(int)BYTE_ORDER," \
+ " rate=(int)44100," \
+ " channels=(int)[1,MAX]"
+
+/*
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("ANY")
);
+*/
-GST_BOILERPLATE (GstAubioTempo, gst_aubiotempo, GstElement,
- GST_TYPE_ELEMENT);
+GST_BOILERPLATE (GstAubioTempo, gst_aubiotempo, GstAudioFilter,
+ GST_TYPE_AUDIO_FILTER);
static void gst_aubiotempo_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_aubiotempo_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static gboolean gst_aubiotempo_set_caps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_aubiotempo_chain (GstPad * pad, GstBuffer * buf);
+//static gboolean gst_aubiotempo_set_caps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_aubiotempo_transform_ip (GstBaseTransform * trans, GstBuffer * buf);
+/* GObject vmethod implementations */
static void
gst_aubiotempo_base_init (gpointer gclass)
{
- static GstElementDetails element_details = {
- "Aubio Tempo Analysis",
- "Analyzer/AubioTempo",
- "Extract tempo period and beat locations using aubio",
- "Paul Brossier <piem@piem.org>"
- };
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+ GstCaps *caps;
+
+ caps = gst_caps_from_string (ALLOWED_CAPS);
+
+ gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (gclass),
+ caps);
+
+ gst_caps_unref (caps);
+
+ /*
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
+ */
+
gst_element_class_set_details (element_class, &element_details);
+
}
/* initialize the plugin's class */
static void
gst_aubiotempo_class_init (GstAubioTempoClass * klass)
{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+ GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
+ //GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (klass);
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
+ //trans_class->stop = GST_DEBUG_FUNCPTR (gst_aubiotempo_stop);
+ //trans_class->event = GST_DEBUG_FUNCPTR (gst_aubiotempo_event);
+ trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_aubiotempo_transform_ip);
+ trans_class->passthrough_on_same_caps = TRUE;
gobject_class->set_property = gst_aubiotempo_set_property;
gobject_class->get_property = gst_aubiotempo_get_property;
- g_object_class_install_property (gobject_class, ARG_SILENT,
+ g_object_class_install_property (gobject_class, PROP_SILENT,
g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
FALSE, G_PARAM_READWRITE));
}
gst_aubiotempo_init (GstAubioTempo * filter,
GstAubioTempoClass * gclass)
{
- GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
-
- filter->sinkpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
- "sink"), "sink");
- gst_pad_set_setcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_aubiotempo_set_caps));
- gst_pad_set_getcaps_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
-
- filter->srcpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
- "src"), "src");
- gst_pad_set_getcaps_function (filter->srcpad,
- GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
-
- gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
- gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
- gst_pad_set_chain_function (filter->sinkpad,
- GST_DEBUG_FUNCPTR(gst_aubiotempo_chain));
- filter->silent = FALSE;
+
+ filter->silent = TRUE;
+
+ filter->type_onset = aubio_onset_kl;
+
+ filter->buf_size = 1024;
+ filter->hop_size = 512;
+ filter->channels = 1;
+
+ filter->ibuf = new_fvec(filter->hop_size, filter->channels);
+ filter->out = new_fvec(2,filter->channels);
+ filter->t = new_aubio_tempo(filter->type_onset,
+ filter->buf_size, filter->hop_size, filter->channels);
}
static void
GstAubioTempo *filter = GST_AUBIOTEMPO (object);
switch (prop_id) {
- case ARG_SILENT:
+ case PROP_SILENT:
filter->silent = g_value_get_boolean (value);
break;
default:
GstAubioTempo *filter = GST_AUBIOTEMPO (object);
switch (prop_id) {
- case ARG_SILENT:
+ case PROP_SILENT:
g_value_set_boolean (value, filter->silent);
break;
default:
/* GstElement vmethod implementations */
/* this function handles the link with other elements */
+/*
static gboolean
gst_aubiotempo_set_caps (GstPad * pad, GstCaps * caps)
{
return gst_pad_set_caps (pad, caps);
}
+*/
/* chain function
* this function does the actual processing
*/
static GstFlowReturn
-gst_aubiotempo_chain (GstPad * pad, GstBuffer * buf)
+gst_aubiotempo_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
{
- GstAubioTempo *filter;
-
- filter = GST_AUBIOTEMPO (GST_OBJECT_PARENT (pad));
-
- if (filter->silent == FALSE)
- g_print ("I'm plugged, therefore I'm in.\n");
+ uint j;
+ GstAubioTempo *filter = GST_AUBIOTEMPO (trans);
+ GstAudioFilter *audiofilter = GST_AUDIO_FILTER(trans);
+
+ gint nsamples = GST_BUFFER_SIZE (buf) / (4 * audiofilter->format.channels);
+
+ /* block loop */
+ for (j = 0; j < nsamples; j++) {
+ /* copy input to ibuf */
+ fvec_write_sample(filter->ibuf, (smpl_t)(GST_BUFFER_DATA(buf)[j]), 0, filter->pos);
+
+ if (filter->pos == filter->hop_size - 1) {
+ aubio_tempo(filter->t, filter->ibuf, filter->out);
+
+ if (filter->out->data[0][0]==1) {
+ gint64 now = GST_BUFFER_TIMESTAMP (buf);
+ // correction of inside buffer time
+ //now += GST_FRAMES_TO_CLOCK_TIME(j, audiofilter->format.rate);
+ if (filter->silent == FALSE) {
+ g_print ("beat: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS(now));
+ }
+ }
+
+ filter->pos = -1; /* so it will be zero next j loop */
+ }
+ filter->pos++;
+ }
- /* just push out the incoming buffer without touching it */
- return gst_pad_push (filter->srcpad, buf);
+ return GST_FLOW_OK;
}
* initialize the plug-in itself
* register the element factories and pad templates
* register the features
- *
- * exchange the string 'plugin' with your elemnt name
*/
static gboolean
plugin_init (GstPlugin * plugin)
{
- /* exchange the strings 'plugin' and 'Template plugin' with your
- * plugin name and description */
- GST_DEBUG_CATEGORY_INIT (gst_aubiotempo_debug, "plugin",
- 0, "Template plugin");
+ GST_DEBUG_CATEGORY_INIT (gst_aubiotempo_debug, "aubiotempo",
+ 0, "Aubiotempo plugin");
return gst_element_register (plugin, "aubiotempo",
GST_RANK_NONE, GST_TYPE_AUBIOTEMPO);
GST_VERSION_MINOR,
"aubiotempo",
"Aubiotempo plugin",
- plugin_init, VERSION, "GPL", "GStreamer", "http://gstreamer.net/")
+ plugin_init, VERSION, "GPL", "GStreamer-aubio", "http://aubio.org/")
#define __GST_AUBIOTEMPO_H__
#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/audio/gstaudiofilter.h>
G_BEGIN_DECLS
#define GST_TYPE_AUBIOTEMPO \
(gst_aubiotempo_get_type())
#define GST_AUBIOTEMPO(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUBIOTEMPO,GstAubioTempo))
-#define GST_AUBIOTEMPO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUBIOTEMPO,GstAubioTempoClass))
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AUBIOTEMPO,GstAubioTempo))
#define GST_IS_AUBIOTEMPO(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUBIOTEMPO))
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AUBIOTEMPO))
+#define GST_AUBIOTEMPO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AUBIOTEMPO,GstAubioTempoClass))
#define GST_IS_AUBIOTEMPO_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUBIOTEMPO))
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AUBIOTEMPO))
+#define GST_AUBIOTEMPO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_AUBIOTEMPO, GstAubioTempoClass))
typedef struct _GstAubioTempo GstAubioTempo;
typedef struct _GstAubioTempoClass GstAubioTempoClass;
struct _GstAubioTempo
{
- GstElement element;
+ GstAudioFilter element;
GstPad *sinkpad, *srcpad;
gboolean silent;
+
+ aubio_tempo_t * t;
+ fvec_t * ibuf;
+ fvec_t * out;
+
+ uint buf_size;
+ uint hop_size;
+ uint channels;
+ uint pos;
+
+ aubio_onsetdetection_type type_onset;
+
};
struct _GstAubioTempoClass
{
- GstElementClass parent_class;
+ GstAudioFilterClass parent_class;
};
GType gst_aubiotempo_get_type (void);