From: Chris Cannam Date: Thu, 17 Jul 2008 08:51:13 +0000 (+0000) Subject: * First bit of Vamp v2 work -- add an optional duration to features in X-Git-Tag: hgimport~30 X-Git-Url: https://git.aubio.org/?p=vamp-aubio-plugins.git;a=commitdiff_plain;h=340474448bee6047ee27d4d7b80bd9f1477bc810;ds=sidebyside * First bit of Vamp v2 work -- add an optional duration to features in a backward compatible way. Warning: this code is unstable and experimental and may change significantly in the coming weeks. --- diff --git a/libmain.cpp b/libmain.cpp index 787ef0c..007d209 100644 --- a/libmain.cpp +++ b/libmain.cpp @@ -23,11 +23,35 @@ #include "plugins/Tempo.h" #include "plugins/Silence.h" +template +class VersionedPluginAdapter : public Vamp::PluginAdapterBase +{ +public: + VersionedPluginAdapter(unsigned int v) : PluginAdapterBase(), m_v(v) { } + virtual ~VersionedPluginAdapter() { } + +protected: + Vamp::Plugin *createPlugin(float inputSampleRate) { + P *p = new P(inputSampleRate, m_v); + Vamp::Plugin *plugin = dynamic_cast(p); + return plugin; + } + unsigned int m_v; +}; + static Vamp::PluginAdapter onsetAdapter; static Vamp::PluginAdapter pitchAdapter; -static Vamp::PluginAdapter notesAdapter; static Vamp::PluginAdapter tempoAdapter; -static Vamp::PluginAdapter silenceAdapter; + +// These two plugins both benefit from the Vamp v2 API if available +static VersionedPluginAdapter *notesAdapter = 0; +static VersionedPluginAdapter *silenceAdapter = 0; + +struct Tidy +{ + ~Tidy() { delete notesAdapter; delete silenceAdapter; } +}; +static Tidy tidy; const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion, unsigned int index) @@ -37,9 +61,20 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion, switch (index) { case 0: return onsetAdapter.getDescriptor(); case 1: return pitchAdapter.getDescriptor(); - case 2: return notesAdapter.getDescriptor(); case 3: return tempoAdapter.getDescriptor(); - case 4: return silenceAdapter.getDescriptor(); + + case 2: + if (!notesAdapter) { + notesAdapter = new VersionedPluginAdapter(vampApiVersion); + } + return notesAdapter->getDescriptor(); + + case 4: + if (!silenceAdapter) { + silenceAdapter = new VersionedPluginAdapter(vampApiVersion); + } + return silenceAdapter->getDescriptor(); + default: return 0; } } diff --git a/plugins/Notes.cpp b/plugins/Notes.cpp index 7ac5ef9..8f936d5 100644 --- a/plugins/Notes.cpp +++ b/plugins/Notes.cpp @@ -4,7 +4,7 @@ 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 file copyright 2006-2008 Chris Cannam and QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -22,8 +22,9 @@ using std::vector; using std::cerr; using std::endl; -Notes::Notes(float inputSampleRate) : +Notes::Notes(float inputSampleRate, unsigned int apiVersion) : Plugin(inputSampleRate), + m_apiVersion(apiVersion), m_ibuf(0), m_fftgrain(0), m_onset(0), @@ -43,6 +44,10 @@ Notes::Notes(float inputSampleRate) : m_avoidLeaps(false), m_prevPitch(-1) { + if (apiVersion == 1) { + cerr << "vamp-aubio: WARNING: using compatibility version 1 of the Vamp API for note\n" + << "tracker plugin: upgrade your host to v2 for proper duration support" << endl; + } } Notes::~Notes() @@ -83,7 +88,8 @@ Notes::getMaker() const int Notes::getPluginVersion() const { - return 1; + if (m_apiVersion == 1) return 2; + return 3; } string @@ -320,10 +326,18 @@ Notes::getOutputDescriptors() const d.name = "Notes"; d.unit = "Hz"; d.hasFixedBinCount = true; - d.binCount = 2; - d.binNames.push_back("Frequency"); - d.binNames.push_back("Duration"); - d.binNames.push_back("Velocity"); + + if (m_apiVersion == 1) { + d.binCount = 3; + d.binNames.push_back("Frequency"); + d.binNames.push_back("Duration"); + d.binNames.push_back("Velocity"); + } else { + d.binCount = 2; + d.binNames.push_back("Frequency"); + d.binNames.push_back("Velocity"); + } + d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::VariableSampleRate; @@ -429,9 +443,19 @@ Notes::pushNote(FeatureSet &fs, const Vamp::RealTime &offTime) if (m_currentOnset < m_delay) m_currentOnset = m_delay; feature.timestamp = m_currentOnset - m_delay; feature.values.push_back(freq); - feature.values.push_back - (Vamp::RealTime::realTime2Frame(offTime, lrintf(m_inputSampleRate)) - - Vamp::RealTime::realTime2Frame(m_currentOnset, lrintf(m_inputSampleRate))); + + if (m_apiVersion == 1) { + feature.values.push_back + (Vamp::RealTime::realTime2Frame + (offTime, lrintf(m_inputSampleRate)) - + Vamp::RealTime::realTime2Frame + (m_currentOnset, lrintf(m_inputSampleRate))); + feature.hasDuration = false; + } else { + feature.hasDuration = true; + feature.duration = offTime - m_currentOnset; + } + feature.values.push_back(m_currentLevel); fs[0].push_back(feature); } diff --git a/plugins/Notes.h b/plugins/Notes.h index 3fc488b..c8141b9 100644 --- a/plugins/Notes.h +++ b/plugins/Notes.h @@ -25,7 +25,7 @@ class Notes : public Vamp::Plugin { public: - Notes(float inputSampleRate); + Notes(float inputSampleRate, unsigned int apiVersion); virtual ~Notes(); bool initialise(size_t channels, size_t stepSize, size_t blockSize); @@ -55,6 +55,7 @@ public: FeatureSet getRemainingFeatures(); protected: + int m_apiVersion; fvec_t *m_ibuf; cvec_t *m_fftgrain; fvec_t *m_onset; diff --git a/plugins/Silence.cpp b/plugins/Silence.cpp index c7d2713..7369276 100644 --- a/plugins/Silence.cpp +++ b/plugins/Silence.cpp @@ -4,7 +4,7 @@ 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 file copyright 2006-2008 Chris Cannam and QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -21,8 +21,9 @@ using std::vector; using std::cerr; using std::endl; -Silence::Silence(float inputSampleRate) : +Silence::Silence(float inputSampleRate, unsigned int apiVersion) : Plugin(inputSampleRate), + m_apiVersion(apiVersion), m_ibuf(0), m_pbuf(0), m_tmpptrs(0), @@ -30,6 +31,10 @@ Silence::Silence(float inputSampleRate) : m_prevSilent(false), m_first(true) { + if (m_apiVersion == 1) { + cerr << "vamp-aubio: WARNING: using compatibility version 1 of the Vamp API for silence\n" + << "detector plugin: upgrade your host to v2 for proper duration support" << endl; + } } Silence::~Silence() @@ -66,7 +71,8 @@ Silence::getMaker() const int Silence::getPluginVersion() const { - return 1; + if (m_apiVersion == 1) return 2; + return 3; } string @@ -150,23 +156,51 @@ Silence::getOutputDescriptors() const OutputList list; OutputDescriptor d; - d.identifier = "silencestart"; - d.name = "Beginnings 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; - d.sampleRate = 0; - 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; - d.sampleRate = 0; - list.push_back(d); + if (m_apiVersion == 1) { + + d.identifier = "silencestart"; + d.name = "Beginnings of Silent Regions"; + d.description = "Return a single instant at the point where each silent region begins"; + d.hasFixedBinCount = true; + d.binCount = 0; + d.hasKnownExtents = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + 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.hasKnownExtents = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + list.push_back(d); + + } else { + + d.identifier = "silent"; + d.name = "Silent Regions"; + d.description = "Return an interval covering each silent region"; + d.hasFixedBinCount = true; + d.binCount = 0; + d.hasKnownExtents = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + list.push_back(d); + + d.identifier = "noisy"; + d.name = "Non-Silent Regions"; + d.description = "Return an interval covering each non-silent region"; + d.hasFixedBinCount = true; + d.binCount = 0; + d.hasKnownExtents = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + list.push_back(d); + } d.identifier = "silencelevel"; d.name = "Silence Test"; @@ -249,13 +283,30 @@ Silence::process(const float *const *inputBuffers, 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); + if (m_apiVersion == 1) { + if (silent) { + returnFeatures[0].push_back(feature); + } else { + returnFeatures[1].push_back(feature); + } } else { - returnFeatures[1].push_back(feature); - } + if (!m_first) { + feature.timestamp = m_lastChange; + feature.hasDuration = true; + feature.duration = featureStamp - m_lastChange; + if (silent) { + // becoming silent, so this is a non-silent region + returnFeatures[1].push_back(feature); + } else { + // becoming non-silent, so this is a silent region + returnFeatures[0].push_back(feature); + } + } + m_lastChange = featureStamp; + } m_prevSilent = silent; m_first = false; @@ -268,12 +319,31 @@ Silence::process(const float *const *inputBuffers, m_ibuf->data = m_pbuf->data; m_pbuf->data = tmpdata; + m_lastTimestamp = timestamp; + return returnFeatures; } Silence::FeatureSet Silence::getRemainingFeatures() { + FeatureSet returnFeatures; + + if (m_prevSilent) { + if (m_lastTimestamp > m_lastChange) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_lastChange; + feature.hasDuration = true; + feature.duration = m_lastTimestamp - m_lastChange; + if (m_prevSilent) { + returnFeatures[0].push_back(feature); + } else { + returnFeatures[1].push_back(feature); + } + } + } + return FeatureSet(); } diff --git a/plugins/Silence.h b/plugins/Silence.h index 35b3fad..eb7c89e 100644 --- a/plugins/Silence.h +++ b/plugins/Silence.h @@ -23,7 +23,7 @@ class Silence : public Vamp::Plugin { public: - Silence(float inputSampleRate); + Silence(float inputSampleRate, unsigned int apiVersion); virtual ~Silence(); bool initialise(size_t channels, size_t stepSize, size_t blockSize); @@ -53,6 +53,7 @@ public: FeatureSet getRemainingFeatures(); protected: + unsigned int m_apiVersion; fvec_t *m_ibuf; fvec_t *m_pbuf; smpl_t **m_tmpptrs; @@ -62,6 +63,8 @@ protected: size_t m_channelCount; bool m_prevSilent; bool m_first; + Vamp::RealTime m_lastChange; + Vamp::RealTime m_lastTimestamp; };