audio_common
audio_common copied to clipboard
capture timestamped audio (ros ticket #20)
I have added a new node (and msg) that enables the ability to capture timestamped audio (in raw). This would be useful for precisely determining when captured sounds happen, such as the click from an SLR camera, and then they can be synchronised with other sensors.
Here is a patch in case this can be added to the project.
trac data:
- Owner: ahendrix
- Reporter: mikebosse
- Reported at: Mon Oct 29 20:34:52 2012
- URL: https://kforge.ros.org/audiocommon/trac//ticket/20
Is there a reason this isnt merged yet? The link seems to not exist anymore.
Yes. The link (and the patch) were lost when kforge was shut down.
I spoke to a friend and they were able to retrieve the patch from a backup.
It was submitted 4 years ago against a version of the package that used rosbuild, so it will probably need some work to update it. I don't have the time, but here's the patch if you're interested:
# HG changeset patch
# User Mike Bosse <[email protected]>
# Date 2012-10-30 12:42:08 +1000
# Node ID 41867e966e88da6df23521e150724be6901e0197
# Parent 13166e69e1eef5c96b9f8c9ec3f2040b1389805a
added message and node to capture timestamped audio data in raw format
diff --git a/audio_capture/CMakeLists.txt b/audio_capture/CMakeLists.txt
--- a/audio_capture/CMakeLists.txt
+++ b/audio_capture/CMakeLists.txt
@@ -23,4 +23,6 @@
include_directories(${GST_INCLUDE_DIRS})
rosbuild_add_executable(audio_capture src/audio_capture.cpp)
target_link_libraries(audio_capture ${GST_LIBRARIES})
+rosbuild_add_executable(audiostampedraw_capture src/audiostampedraw_capture.cpp)
+target_link_libraries(audiostampedraw_capture ${GST_LIBRARIES})
rosbuild_link_boost(audio_capture thread)
diff --git a/audio_capture/launch/capture_stampedraw.launch b/audio_capture/launch/capture_stampedraw.launch
new file mode 100644
--- /dev/null
+++ b/audio_capture/launch/capture_stampedraw.launch
@@ -0,0 +1,6 @@
+<launch>
+
+ <node name="audio_capture" pkg="audio_capture" type="audiostampedraw_capture" output="screen">
+ </node>
+
+</launch>
diff --git a/audio_capture/src/audiostampedraw_capture.cpp b/audio_capture/src/audiostampedraw_capture.cpp
new file mode 100644
--- /dev/null
+++ b/audio_capture/src/audiostampedraw_capture.cpp
@@ -0,0 +1,145 @@
+#include <stdio.h>
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+#include <boost/thread.hpp>
+
+#include <ros/ros.h>
+
+#include "audio_common_msgs/AudioDataStampedRaw.h"
+
+namespace audio_transport
+{
+ class RosGstCapture
+ {
+ public:
+ RosGstCapture()
+ {
+ _bitrate = 192;
+
+ std::string dst_type;
+
+ // The bitrate at which to encode the audio
+ ros::param::param<int>("~bitrate", _bitrate, 192);
+
+ // The destination of the audio
+ ros::param::param<std::string>("~dst", dst_type, "appsink");
+
+ // The source of the audio
+ //ros::param::param<std::string>("~src", source_type, "alsasrc");
+
+ _pub = _nh.advertise<audio_common_msgs::AudioDataStampedRaw>("audio", 10, true);
+
+ _loop = g_main_loop_new(NULL, false);
+ _pipeline = gst_pipeline_new("ros_pipeline");
+
+ // We create the sink first, just for convenience
+ if (dst_type == "appsink")
+ {
+ _sink = gst_element_factory_make("appsink", "sink");
+ g_object_set(G_OBJECT(_sink), "emit-signals", true, NULL);
+ g_object_set(G_OBJECT(_sink), "max-buffers", 100, NULL);
+ g_signal_connect( G_OBJECT(_sink), "new-buffer",
+ G_CALLBACK(onNewBuffer), this);
+ }
+ else
+ {
+ printf("file sink\n");
+ _sink = gst_element_factory_make("filesink", "sink");
+ g_object_set( G_OBJECT(_sink), "location", dst_type.c_str(), NULL);
+ }
+
+ _source = gst_element_factory_make("alsasrc", "source");
+ _convert = gst_element_factory_make("audioconvert", "convert");
+
+#if 0
+ _encode = gst_element_factory_make("lame", "encoder");
+ g_object_set( G_OBJECT(_encode), "preset", 1001, NULL);
+ g_object_set( G_OBJECT(_encode), "bitrate", _bitrate, NULL);
+
+
+ gst_bin_add_many( GST_BIN(_pipeline), _source, _convert, _encode, _sink, NULL);
+ gst_element_link_many(_source, _convert, _encode, _sink, NULL);
+#else
+ // remove _encode so that we have raw audio
+ gst_bin_add_many( GST_BIN(_pipeline), _source, _convert, _sink, NULL);
+ gst_element_link_many(_source, _convert, _sink, NULL);
+
+ GstCaps *caps = gst_caps_new_simple("audio/x-raw-int",
+ "channels",G_TYPE_INT,1,
+ "width",G_TYPE_INT,8,
+ "depth",G_TYPE_INT,8,
+ NULL);
+
+ g_object_set( G_OBJECT(_sink), "caps", caps, NULL);
+
+ gst_caps_unref(caps);
+#endif
+ /*}
+ else
+ {
+ _sleep_time = 10000;
+ _source = gst_element_factory_make("filesrc", "source");
+ g_object_set(G_OBJECT(_source), "location", source_type.c_str(), NULL);
+
+ gst_bin_add_many( GST_BIN(_pipeline), _source, _sink, NULL);
+ gst_element_link_many(_source, _sink, NULL);
+ }
+ */
+
+ // setup the pipeline to use the system clock in real time mode
+ _sysclock = gst_system_clock_obtain();
+ g_object_set( G_OBJECT(_sysclock), "clock-type", GST_CLOCK_TYPE_REALTIME, NULL);
+ gst_pipeline_use_clock(GST_PIPELINE(_pipeline),_sysclock);
+
+ gst_element_set_state(GST_ELEMENT(_pipeline), GST_STATE_PLAYING);
+ //_sysclock = gst_pipeline_get_clock(GST_PIPELINE(_pipeline));
+
+ _gst_thread = boost::thread( boost::bind(g_main_loop_run, _loop) );
+ }
+
+ void publish( const audio_common_msgs::AudioDataStampedRaw &msg )
+ {
+ _pub.publish(msg);
+ }
+
+ static GstFlowReturn onNewBuffer (GstAppSink *appsink, gpointer userData)
+ {
+ RosGstCapture *server = reinterpret_cast<RosGstCapture*>(userData);
+ audio_common_msgs::AudioDataStampedRaw msg;
+
+ GstBuffer *buffer;
+ g_signal_emit_by_name(appsink, "pull-buffer", &buffer);
+
+ msg.header.stamp = ros::Time::now().fromNSec(buffer->timestamp + gst_element_get_base_time(GST_ELEMENT(server->_pipeline)) );
+
+ msg.data.resize( buffer->size );
+ memcpy( &msg.data[0], buffer->data, buffer->size);
+
+ server->publish(msg);
+
+ gst_buffer_unref(buffer);
+
+ return GST_FLOW_OK;
+ }
+
+ private:
+ ros::NodeHandle _nh;
+ ros::Publisher _pub;
+
+ boost::thread _gst_thread;
+
+ GstElement *_pipeline, *_source, *_sink, *_convert, *_encode;
+ GstClock *_sysclock;
+ GMainLoop *_loop;
+ int _bitrate;
+ };
+}
+
+int main (int argc, char **argv)
+{
+ ros::init(argc, argv, "audio_capture");
+ gst_init(&argc, &argv);
+
+ audio_transport::RosGstCapture server;
+ ros::spin();
+}
diff --git a/audio_common_msgs/msg/AudioDataStampedRaw.msg b/audio_common_msgs/msg/AudioDataStampedRaw.msg
new file mode 100644
--- /dev/null
+++ b/audio_common_msgs/msg/AudioDataStampedRaw.msg
@@ -0,0 +1,2 @@
+Header header
+uint8[] data