[gstreamer-bugs] [Bug 597822] Add removesilence plugin

GStreamer (bugzilla.gnome.org) bugzilla at gnome.org
Thu Oct 8 11:57:18 PDT 2009


https://bugzilla.gnome.org/show_bug.cgi?id=597822
  GStreamer | gst-plugins-bad | git

--- Comment #1 from tiagokatcipis at gmail.com 2009-10-08 15:41:31 UTC ---
im not being able to upload he patch, it keeps telling me that the file does
not exist or that i dont have permission to read it....but it does exists and i
can read it. So im pasting here the patch content:

>From 4d87bc4d7a15212acf7c568af25379b4cc15193b Mon Sep 17 00:00:00 2001
From: Tiago Katcipis <katcipis at katcipis-laptop.(none)>
Date: Thu, 8 Oct 2009 12:04:18 -0300
Subject: [PATCH] adding removesilence plugin

---
 configure.ac                         |    2 +
 gst/removesilence/Makefile.am        |   12 ++
 gst/removesilence/gstremovesilence.c |  345 ++++++++++++++++++++++++++++++++++
 gst/removesilence/gstremovesilence.h |   70 +++++++
 gst/removesilence/vad_private.c      |  134 +++++++++++++
 gst/removesilence/vad_private.h      |   66 +++++++
 6 files changed, 629 insertions(+), 0 deletions(-)
 create mode 100644 gst/removesilence/Makefile.am
 create mode 100644 gst/removesilence/gstremovesilence.c
 create mode 100644 gst/removesilence/gstremovesilence.h
 create mode 100644 gst/removesilence/vad_private.c
 create mode 100644 gst/removesilence/vad_private.h

diff --git a/configure.ac b/configure.ac
index 7c32666..55b05d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -285,6 +285,7 @@ AG_GST_CHECK_PLUGIN(pnm)
 AG_GST_CHECK_PLUGIN(qtmux)
 AG_GST_CHECK_PLUGIN(rawparse)
 AG_GST_CHECK_PLUGIN(real)
+AG_GST_CHECK_PLUGIN(removesilence)
 AG_GST_CHECK_PLUGIN(rtpmux)
 AG_GST_CHECK_PLUGIN(scaletempo)
 AG_GST_CHECK_PLUGIN(sdp)
@@ -1767,6 +1768,7 @@ gst/pnm/Makefile
 gst/qtmux/Makefile
 gst/rawparse/Makefile
 gst/real/Makefile
+gst/removesilence/Makefile
 gst/rtpmux/Makefile
 gst/scaletempo/Makefile
 gst/sdp/Makefile
diff --git a/gst/removesilence/Makefile.am b/gst/removesilence/Makefile.am
new file mode 100644
index 0000000..700df47
--- /dev/null
+++ b/gst/removesilence/Makefile.am
@@ -0,0 +1,12 @@
+
+plugin_LTLIBRARIES = libgstremovesilence.la
+
+libgstremovesilence_la_SOURCES = gstremovesilence.c vad_private.c
+libgstremovesilence_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
+libgstremovesilence_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
$(GST_PLUGINS_BASE_LIBS)
+libgstremovesilence_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstremovesilence_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = \
+    gstremovesilence.h \
+    vad_private.h
diff --git a/gst/removesilence/gstremovesilence.c
b/gst/removesilence/gstremovesilence.c
new file mode 100644
index 0000000..625bf8f
--- /dev/null
+++ b/gst/removesilence/gstremovesilence.c
@@ -0,0 +1,345 @@
+/*
+ * GStreamer
+ * @author Tiago Katcipis <tiagokatcipis at gmail.com>
+ * @author Paulo Pizarro  <paulo.pizarro at gmail.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-removesilence
+ *
+ * Removes all silence periods from an audio stream, fixing timestamp
discontinuities.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m filesrc location="audiofile" ! decodebin ! removesilence !
autoaudiosink
+ * ]|
+ * </refsect2>
+ */
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include "gstremovesilence.h"
+#include "vad_private.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_remove_silence_debug);
+#define GST_CAT_DEFAULT gst_remove_silence_debug
+
+struct _GstRemoveSilence
+{
+  GstElement element;
+  GstPad *sinkpad, *srcpad;
+  VADFilter* vad;
+  gboolean remove;
+  gint64 segment_end;
+  gint samplerate;
+  GstClockTime last_timestamp;
+};
+
+struct _GstRemoveSilenceClass 
+{
+  GstElementClass parent_class;
+};
+
+/* Filter signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_REMOVE
+};
+
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, rate=[1, 2147483647], channels=1,
endianness=1234, width=16, depth=16, signed=true")
+    );
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, rate=[1, 2147483647], channels=1,
endianness=1234, width=16, depth=16, signed=true")
+    );
+
+GST_BOILERPLATE (GstRemoveSilence, gst_remove_silence, GstElement,
GST_TYPE_ELEMENT);
+
+static void gst_remove_silence_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_remove_silence_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static gboolean gst_remove_silence_set_caps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_remove_silence_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_remove_silence_event (GstPad * pad, GstEvent * event);
+
+/* GObject vmethod implementations */
+
+static void
+gst_remove_silence_base_init (gpointer gclass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+  gst_element_class_set_details_simple(element_class,
+    "RemoveSilence",
+    "Filter/Effect/Audio",
+    "Removes all the silence periods from the stream.",
+    "Tiago Katcipis <tiagokatcipis at gmail.com>\n \
+     Paulo Pizarro  <paulo.pizarro at gmail.com>");
+
+  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));
+}
+
+/* initialize the removesilence's class */
+static void
+gst_remove_silence_class_init (GstRemoveSilenceClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_remove_silence_set_property;
+  gobject_class->get_property = gst_remove_silence_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_REMOVE,
+      g_param_spec_boolean ("remove", "Remove", "Set to true to remove silence
from the stream, false otherwhise",
+          FALSE, G_PARAM_READWRITE));
+}
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_remove_silence_init (GstRemoveSilence * filter,
+    GstRemoveSilenceClass * gclass)
+{
+  filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
+  gst_pad_set_setcaps_function (filter->sinkpad,
+                               
GST_DEBUG_FUNCPTR(gst_remove_silence_set_caps));
+  gst_pad_set_getcaps_function (filter->sinkpad,
+                                GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
+  gst_pad_set_chain_function (filter->sinkpad,
+                              GST_DEBUG_FUNCPTR(gst_remove_silence_chain));
+
+  filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+  gst_pad_set_getcaps_function (filter->srcpad,
+                                GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
+  
+  gst_pad_set_event_function (filter->sinkpad, gst_remove_silence_event);
+
+  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
+
+  filter->remove = FALSE;
+  filter->last_timestamp = 0;
+  filter->vad = vad_new();
+  if(!filter->vad){
+      GST_DEBUG("Error initializing VAD !!");
+      return;
+  }
+}
+
+static void
+gst_remove_silence_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstRemoveSilence *filter = GST_REMOVESILENCE (object);
+
+  switch (prop_id) {
+    case PROP_REMOVE:
+      filter->remove = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_remove_silence_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstRemoveSilence *filter = GST_REMOVESILENCE (object);
+
+  switch (prop_id) {
+    case PROP_REMOVE:
+      g_value_set_boolean (value, filter->remove);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* this function handles the link with other elements */
+static gboolean
+gst_remove_silence_set_caps (GstPad * pad, GstCaps * caps)
+{
+  GstRemoveSilence *filter;
+  GstPad *otherpad;
+  GstStructure *structure = gst_caps_get_structure(caps, 0);
+
+  filter = GST_REMOVESILENCE (gst_pad_get_parent (pad));
+  otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
+
+  if(!gst_pad_set_caps (otherpad, caps))
+    return FALSE;
+  
+  gst_structure_get_int (structure, "rate", &filter->samplerate);
+  return TRUE; 
+}
+
+static GstFlowReturn
+gst_remove_silence_chain (GstPad * pad, GstBuffer * inbuf)
+{
+  GstRemoveSilence *filter = NULL;
+  int frame_type;
+  filter = GST_REMOVESILENCE (GST_OBJECT_PARENT (pad));
+  
+  /*
+    Validate timestamp, some elements does not control the segment being
played
+    using timestamp, if you are looping on a segment with silence a skew can
be generated
+    because the stream will emit segment end based on the audio played not the
timestamp. 
+  */
+  if(filter->remove){
+      if(GST_BUFFER_CAST(inbuf)->timestamp > filter->segment_end){
+          //Reached the end of the segment
+          GST_DEBUG("EOS reached!");
+          GST_DEBUG("buffer timestamp[%lli], segment_end[%lli]",
GST_BUFFER_CAST(inbuf)->timestamp, filter->segment_end);
+          gst_buffer_unref(inbuf);
+          return GST_FLOW_UNEXPECTED;
+      }
+  }
+  frame_type = vad_update(filter->vad, (short *) GST_BUFFER_DATA(inbuf),
GST_BUFFER_SIZE(inbuf) / sizeof(short));
+  if (frame_type == VAD_SILENCE) {
+      GST_DEBUG("Silence detected!");
+      if(filter->remove){
+          GST_DEBUG("Removing silence!");
+          gst_buffer_unref(inbuf);
+          return GST_FLOW_OK;    
+      }
+  } 
+
+  GST_DEBUG("Voice!");      
+  GST_BUFFER_CAST(inbuf)->timestamp = filter->last_timestamp;
+  filter->last_timestamp += GST_BUFFER_DURATION(inbuf);
+  
+  return gst_pad_push (filter->srcpad, inbuf);
+}
+
+
+static gboolean gst_remove_handle_new_segment_event(GstRemoveSilence* filter,
GstEvent* event)
+{
+    gdouble rate = 0.0;
+    gboolean update = FALSE;
+    gint64 start,stop,position;
+    GstFormat format;
+
+    gst_event_parse_new_segment(event, &update, &rate, &format,  
+                                &start, &stop, &position);
+
+    GST_DEBUG("Updating segment: update[%d], rate[%f], format[%d],
start[%lli], stop[%lli], position[%lli]",
+              update, rate, format, start, stop, position);
+
+    if(format == GST_FORMAT_TIME){
+        GST_DEBUG("Getting new segment in time");
+        filter->segment_end = stop;
+        filter->last_timestamp = start;
+        return TRUE;
+    }
+
+    if(format == GST_FORMAT_BYTES){
+        GST_DEBUG("Getting new segment in bytes");
+        filter->segment_end = (stop / sizeof(short)) / (filter->samplerate /
GST_SECOND);
+        filter->last_timestamp = (start / sizeof(short)) / (filter->samplerate
/ GST_SECOND);
+        return TRUE;
+    }
+
+    GST_DEBUG("Unable to get the segment being played");
+    return FALSE;
+}
+
+static gboolean gst_remove_silence_event (GstPad * pad, GstEvent * event)
+{
+    GstRemoveSilence* filter = GST_REMOVESILENCE (GST_OBJECT_PARENT (pad));
+    gboolean ret = FALSE;
+
+    switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+      if(!gst_remove_handle_new_segment_event(filter, event)){
+          return FALSE;
+      }
+      ret = gst_pad_push_event (filter->srcpad, event);
+      break;
+    default:
+        ret = gst_pad_event_default(pad, event);
+        break;
+    }
+    return ret;
+}
+
+/*Plugin init functions*/
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "removesilence", GST_RANK_NONE,
gst_remove_silence_get_type());
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "removesilence",
+    "Removes silence from an audio stream",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
+
diff --git a/gst/removesilence/gstremovesilence.h
b/gst/removesilence/gstremovesilence.h
new file mode 100644
index 0000000..276b963
--- /dev/null
+++ b/gst/removesilence/gstremovesilence.h
@@ -0,0 +1,70 @@
+/*
+ * GStreamer
+ * @author Tiago Katcipis <tiagokatcipis at gmail.com>
+ * @author Paulo Pizarro  <paulo.pizarro at gmail.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_REMOVESILENCE_H__
+#define __GST_REMOVESILENCE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_REMOVESILENCE \
+  (gst_remove_silence_get_type())
+#define GST_REMOVESILENCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_REMOVESILENCE,GstRemoveSilence))
+#define GST_REMOVESILENCE_CLASS(klass) \
+ 
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_REMOVESILENCE,GstRemoveSilenceClass))
+#define GST_IS_REMOVESILENCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_REMOVESILENCE))
+#define GST_IS_REMOVESILENCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_REMOVESILENCE))
+
+typedef struct _GstRemoveSilence      GstRemoveSilence;
+typedef struct _GstRemoveSilenceClass GstRemoveSilenceClass;
+
+GType gst_remove_silence_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_REMOVESILENCE_H__ */
diff --git a/gst/removesilence/vad_private.c b/gst/removesilence/vad_private.c
new file mode 100644
index 0000000..54cbf21
--- /dev/null
+++ b/gst/removesilence/vad_private.c
@@ -0,0 +1,134 @@
+/*
+ * GStreamer
+ * @author Tiago Katcipis <tiagokatcipis at gmail.com>
+ * @author Paulo Pizarro  <paulo.pizarro at gmail.com>
+ * @author Rogério Santos <rogerio.santos at digitro.com.br>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "vad_private.h"
+#include <string.h>
+
+union pgen {
+    unsigned long a;
+    void *v;
+    unsigned long *l;
+    unsigned char *b;
+    unsigned short *w;
+    short *s;
+};
+
+struct _cqueue_s {
+    union pgen base;
+    union pgen tail;
+    union pgen head;
+    int size;
+};
+
+typedef struct _cqueue_s cqueue_t;
+
+struct _vad_s {
+    short vad_buffer[VAD_BUFFER_SIZE];
+    cqueue_t cqueue;
+    int vad_state;
+    unsigned long vad_samples;
+    unsigned long vad_power;
+    long vad_zcr;
+};
+
+VADFilter* vad_new()
+{
+    VADFilter* vad = malloc(sizeof(VADFilter));
+    memset(vad, 0, sizeof(vad));
+    vad->cqueue.base.s = vad->vad_buffer;
+    vad->cqueue.tail.a = vad->cqueue.head.a = 0;
+    vad->cqueue.size = VAD_BUFFER_SIZE;
+    return vad;
+}
+
+int vad_update(struct _vad_s *p, short *data, int len)
+{
+    unsigned long tail;
+    int frame_type;
+    short sample;
+    int i;
+
+    for (i = 0; i < len; i++) {
+        p->vad_power = VAD_POWER_ALPHA * ((data[i] * data[i] >> 14) & 0xFFFF)
+ \
+                       (0xFFFF - VAD_POWER_ALPHA) * (p->vad_power >> 16) + \
+                        ((0xFFFF - VAD_POWER_ALPHA) * (p->vad_power & 0xFFFF)
>> 16);
+        /* Update VAD buffer */
+        p->cqueue.base.s[p->cqueue.head.a] = data[i];
+        p->cqueue.head.a = ++p->cqueue.head.a & (p->cqueue.size - 1); 
+        if (p->cqueue.head.a == p->cqueue.tail.a)
+            p->cqueue.tail.a = ++p->cqueue.tail.a & (p->cqueue.size - 1); 
+    }
+
+    tail = p->cqueue.tail.a;
+    p->vad_zcr = 0;
+    for (;;) {
+        sample = p->cqueue.base.s[tail];
+        tail = (tail + 1) & (p->cqueue.size - 1);
+        if (tail == p->cqueue.head.a) break;
+        p->vad_zcr += ((sample & 0x8000) != (p->cqueue.base.s[tail] & 0x8000))
? 1 : -1;
+    }
+
+    frame_type = (p->vad_power > VAD_POWER_THRESHOLD && p->vad_zcr <
VAD_ZCR_THRESHOLD) ? VAD_VOICE : VAD_SILENCE;
+
+    if (p->vad_state != frame_type) {
+        /* Voice to silence transition */
+        if (p->vad_state == VAD_VOICE) {
+            p->vad_samples += len;
+            if (p->vad_samples >= VAD_HYSTERESIS) {
+                p->vad_state = frame_type;
+                p->vad_samples = 0;
+            }
+        }
+        else {
+            p->vad_state = frame_type;
+            p->vad_samples = 0;
+        }
+    }
+    else {
+        p->vad_samples = 0;
+    }
+
+    return p->vad_state;
+}
diff --git a/gst/removesilence/vad_private.h b/gst/removesilence/vad_private.h
new file mode 100644
index 0000000..e2d0f70
--- /dev/null
+++ b/gst/removesilence/vad_private.h
@@ -0,0 +1,66 @@
+/*
+ * GStreamer
+ * @author Tiago Katcipis <tiagokatcipis at gmail.com>
+ * @author Paulo Pizarro  <paulo.pizarro at gmail.com>
+ * @author Rogério Santos <rogerio.santos at digitro.com.br>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VAD_FILTER_H__
+#define __VAD_FILTER_H__
+
+#define VAD_SILENCE  0
+#define VAD_VOICE    1
+
+#define VAD_POWER_ALPHA           0x0800        /* Q16 */
+#define VAD_POWER_THRESHOLD       0x000010C7    /* -60 dB (square wave) */
+#define VAD_ZCR_THRESHOLD         0 
+#define VAD_BUFFER_SIZE           256
+#define VAD_HYSTERESIS            480           /* 60 mseg */
+
+#define DEFAULT_ADAPTATIVE_TIMER  100           /* mseg */
+
+typedef struct _vad_s VADFilter;
+
+int vad_update(VADFilter *p, short *data, int len);
+
+VADFilter* vad_new();
+
+#endif /* __VAD_FILTER__ */
-- 
1.6.0.4

-- 
Configure bugmail: https://bugzilla.gnome.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.



More information about the Gstreamer-bugs mailing list