Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

capture timestamped audio (ros ticket #20) #20

Open
ahendrix opened this issue Mar 14, 2013 · 3 comments
Open

capture timestamped audio (ros ticket #20) #20

ahendrix opened this issue Mar 14, 2013 · 3 comments

Comments

@ahendrix
Copy link
Contributor

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:

@avalada
Copy link

avalada commented Jan 19, 2016

Is there a reason this isnt merged yet? The link seems to not exist anymore.

@trainman419
Copy link
Contributor

Yes. The link (and the patch) were lost when kforge was shut down.

@trainman419
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants