* Add silence detector. But I'm not happy with its results: take a look at
authorChris Cannam <cannam@all-day-breakfast.com>
Tue, 9 Oct 2007 15:42:36 +0000 (15:42 +0000)
committerChris Cannam <cannam@all-day-breakfast.com>
Tue, 9 Oct 2007 15:42:36 +0000 (15:42 +0000)
  the aubio silence detection code and see what's up

libmain.cpp
plugins/Silence.cpp [new file with mode: 0644]
plugins/Silence.h [new file with mode: 0644]
vamp-aubio.cat

index 9298fe8..787ef0c 100644 (file)
 #include "plugins/Pitch.h"
 #include "plugins/Notes.h"
 #include "plugins/Tempo.h"
 #include "plugins/Pitch.h"
 #include "plugins/Notes.h"
 #include "plugins/Tempo.h"
+#include "plugins/Silence.h"
 
 static Vamp::PluginAdapter<Onset> onsetAdapter;
 static Vamp::PluginAdapter<Pitch> pitchAdapter;
 static Vamp::PluginAdapter<Notes> notesAdapter;
 static Vamp::PluginAdapter<Tempo> tempoAdapter;
 
 static Vamp::PluginAdapter<Onset> onsetAdapter;
 static Vamp::PluginAdapter<Pitch> pitchAdapter;
 static Vamp::PluginAdapter<Notes> notesAdapter;
 static Vamp::PluginAdapter<Tempo> tempoAdapter;
+static Vamp::PluginAdapter<Silence> silenceAdapter;
 
 const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion,
                                                     unsigned int index)
 
 const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion,
                                                     unsigned int index)
@@ -37,6 +39,7 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion,
     case  1: return pitchAdapter.getDescriptor();
     case  2: return notesAdapter.getDescriptor();
     case  3: return tempoAdapter.getDescriptor();
     case  1: return pitchAdapter.getDescriptor();
     case  2: return notesAdapter.getDescriptor();
     case  3: return tempoAdapter.getDescriptor();
+    case  4: return silenceAdapter.getDescriptor();
     default: return 0;
     }
 }
     default: return 0;
     }
 }
diff --git a/plugins/Silence.cpp b/plugins/Silence.cpp
new file mode 100644 (file)
index 0000000..01d516b
--- /dev/null
@@ -0,0 +1,285 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp feature extraction plugins using Paul Brossier's Aubio library.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+
+*/
+
+#include <math.h>
+#include "Silence.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+Silence::Silence(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_ibuf(0),
+    m_pbuf(0),
+    m_tmpptrs(0),
+    m_threshold(-70),
+    m_prevSilent(false),
+    m_first(true)
+{
+}
+
+Silence::~Silence()
+{
+    if (m_ibuf) del_fvec(m_ibuf);
+    if (m_pbuf) del_fvec(m_pbuf);
+    if (m_tmpptrs) delete[] m_tmpptrs;
+}
+
+string
+Silence::getIdentifier() const
+{
+    return "aubiosilence";
+}
+
+string
+Silence::getName() const
+{
+    return "Aubio Silence Detector";
+}
+
+string
+Silence::getDescription() const
+{
+    return "Detect levels below a certain threshold";
+}
+
+string
+Silence::getMaker() const
+{
+    return "Paul Brossier (plugin by Chris Cannam)";
+}
+
+int
+Silence::getPluginVersion() const
+{
+    return 1;
+}
+
+string
+Silence::getCopyright() const
+{
+    return "GPL";
+}
+
+bool
+Silence::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    m_channelCount = channels;
+    m_stepSize = stepSize;
+    m_blockSize = blockSize;
+
+    m_ibuf = new_fvec(stepSize, channels);
+    m_pbuf = new_fvec(stepSize, channels);
+    m_tmpptrs = new smpl_t *[channels];
+
+    return true;
+}
+
+void
+Silence::reset()
+{
+    m_first = true;
+}
+
+size_t
+Silence::getPreferredStepSize() const
+{
+    return 1024;
+}
+
+size_t
+Silence::getPreferredBlockSize() const
+{
+    return 1024;
+}
+
+Silence::ParameterList
+Silence::getParameterDescriptors() const
+{
+    ParameterList list;
+    ParameterDescriptor desc;
+
+    desc = ParameterDescriptor();
+    desc.identifier = "silencethreshold";
+    desc.name = "Silence Threshold";
+    desc.minValue = -120;
+    desc.maxValue = 0;
+    desc.defaultValue = -70;
+    desc.unit = "dB";
+    desc.isQuantized = false;
+    list.push_back(desc);
+
+    return list;
+}
+
+float
+Silence::getParameter(std::string param) const
+{
+    if (param == "silencethreshold") {
+        return m_threshold;
+    } else {
+        return 0.0;
+    }
+}
+
+void
+Silence::setParameter(std::string param, float value)
+{
+    if (param == "silencethreshold") {
+        m_threshold = value;
+    }
+}
+
+Silence::OutputList
+Silence::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor d;
+    d.identifier = "silencestart";
+    d.name = "Starts of Silent Regions";
+    d.description = "Return a single instant at the point where each silent region begins";
+    d.hasFixedBinCount = true;
+    d.binCount = 0;
+    d.sampleType = OutputDescriptor::VariableSampleRate;
+    list.push_back(d);
+
+    d.identifier = "silenceend";
+    d.name = "Ends of Silent Regions";
+    d.description = "Return a single instant at the point where each silent region ends";
+    d.hasFixedBinCount = true;
+    d.binCount = 0;
+    d.sampleType = OutputDescriptor::VariableSampleRate;
+    list.push_back(d);
+
+    d.identifier = "silencelevel";
+    d.name = "Silence Test";
+    d.description = "Return a function that switches from 1 to 0 when silence falls, and back again when it ends";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.hasKnownExtents = true;
+    d.minValue = 0;
+    d.maxValue = 1;
+    d.isQuantized = true;
+    d.quantizeStep = 1;
+    d.sampleType = OutputDescriptor::VariableSampleRate;
+    list.push_back(d);
+
+    return list;
+}
+
+Silence::FeatureSet
+Silence::process(const float *const *inputBuffers,
+                 Vamp::RealTime timestamp)
+{
+    for (size_t i = 0; i < m_stepSize; ++i) {
+        for (size_t j = 0; j < m_channelCount; ++j) {
+            fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i);
+        }
+    }
+
+    bool silent = aubio_silence_detection(m_ibuf, m_threshold);
+    FeatureSet returnFeatures;
+
+    if (m_first || m_prevSilent != silent) {
+
+        Vamp::RealTime featureStamp = timestamp;
+
+        if ((silent && !m_first) || !silent) {
+        
+            // refine our result
+
+            long off = 0;
+            size_t incr = 16;
+            if (incr > m_stepSize/8) incr = m_stepSize/8;
+
+            fvec_t vec;
+            vec.length = incr * 4;
+            vec.channels = m_channelCount;
+            vec.data = m_tmpptrs;
+            
+            if (silent) {
+                std::cerr << "silence at " << timestamp << std::endl;
+            }
+            
+            for (size_t i = 0; i < m_stepSize - incr * 4; i += incr) {
+                for (size_t j = 0; j < m_channelCount; ++j) {
+                    m_tmpptrs[j] = m_ibuf->data[j] + i;
+                }
+                bool subsilent = aubio_silence_detection(&vec, m_threshold);
+                if (silent == subsilent) {
+                    std::cerr << "silent == subsilent at " << i << " after" << std::endl;
+                    off = i;
+                    break;
+                }
+            }
+
+            if (silent && (off == 0)) {
+                for (size_t i = 0; i < m_stepSize - incr; i += incr) {
+                    for (size_t j = 0; j < m_channelCount; ++j) {
+                        m_tmpptrs[j] = m_pbuf->data[j] + m_stepSize - i - incr;
+                    }
+                    bool subsilent = aubio_silence_detection(&vec, m_threshold);
+                    if (!subsilent) {
+                        std::cerr << "non-silence at " << i << " samples before" << std::endl;
+                        off = -(long)i;
+                        break;
+                    } else {
+                        std::cerr << "silence at " << i << " samples before" << std::endl;
+                    }
+                }
+            } else {
+            }                
+
+            featureStamp = timestamp + Vamp::RealTime::frame2RealTime
+                (off, lrintf(m_inputSampleRate));
+        }
+
+        Feature feature;
+        feature.hasTimestamp = true;
+        feature.timestamp = featureStamp;
+        feature.values.push_back(silent ? 0 : 1);
+        returnFeatures[2].push_back(feature);
+        feature.values.clear();
+
+        if (silent) {
+            returnFeatures[0].push_back(feature);
+        } else {
+            returnFeatures[1].push_back(feature);
+        }            
+
+        m_prevSilent = silent;
+        m_first = false;
+    }
+
+    // swap ibuf and pbuf data pointers, so that this block's data is
+    // available in pbuf when processing the next block, without
+    // having to allocate new storage for it
+    smpl_t **tmpdata = m_ibuf->data;
+    m_ibuf->data = m_pbuf->data;
+    m_pbuf->data = tmpdata;
+
+    return returnFeatures;
+}
+
+Silence::FeatureSet
+Silence::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
diff --git a/plugins/Silence.h b/plugins/Silence.h
new file mode 100644 (file)
index 0000000..35b3fad
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp feature extraction plugins using Paul Brossier's Aubio library.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+
+*/
+
+#ifndef _SILENCE_PLUGIN_H_
+#define _SILENCE_PLUGIN_H_
+
+#include <vamp-sdk/Plugin.h>
+#include <aubio/aubio.h>
+
+class Silence : public Vamp::Plugin
+{
+public:
+    Silence(float inputSampleRate);
+    virtual ~Silence();
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
+
+    InputDomain getInputDomain() const { return TimeDomain; }
+
+    std::string getIdentifier() const;
+    std::string getName() const;
+    std::string getDescription() const;
+    std::string getMaker() const;
+    int getPluginVersion() const;
+    std::string getCopyright() const;
+
+    ParameterList getParameterDescriptors() const;
+    float getParameter(std::string) const;
+    void setParameter(std::string, float);
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    fvec_t *m_ibuf;
+    fvec_t *m_pbuf;
+    smpl_t **m_tmpptrs;
+    float m_threshold;
+    size_t m_stepSize;
+    size_t m_blockSize;
+    size_t m_channelCount;
+    bool m_prevSilent;
+    bool m_first;
+};
+
+
+#endif
index 10ba08c..025f1be 100644 (file)
@@ -2,3 +2,4 @@ vamp:vamp-aubio:aubionotes::Notes
 vamp:vamp-aubio:aubioonset::Time > Onsets
 vamp:vamp-aubio:aubiotempo::Time > Tempo
 vamp:vamp-aubio:aubiopitch::Pitch
 vamp:vamp-aubio:aubioonset::Time > Onsets
 vamp:vamp-aubio:aubiotempo::Time > Tempo
 vamp:vamp-aubio:aubiopitch::Pitch
+vamp:vamp-aubio:aubiosilence::Low Level Features