summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-03-26 14:10:25 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-03-26 14:10:25 +0000
commitc2429bdcd6ed957ff1c0a4600abbe5b0988eeeb3 (patch)
treef45f36294aa40c60a5d59536f7a6f02bec4fef75
parentcb5cb2e7b03e03cbaa185b60da2f253a63d838fa (diff)
rearrange and update VAMP tree to match VAMP 2.0
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4898 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/vamp-sdk/SConscript19
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.cpp)346
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginChannelAdapter.cpp (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp)52
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginHostAdapter.cpp456
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginInputDomainAdapter.cpp (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp)31
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp)22
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp952
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginWrapper.cpp (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp)5
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/RealTime.cpp39
-rw-r--r--libs/vamp-sdk/src/vamp-sdk/PluginAdapter.cpp914
-rw-r--r--libs/vamp-sdk/src/vamp-sdk/RealTime.cpp252
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/Plugin.h47
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginBase.h47
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginBufferingAdapter.h194
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginChannelAdapter.h (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h)25
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginHostAdapter.h123
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginInputDomainAdapter.h (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h)37
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginLoader.h (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h)7
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginSummarisingAdapter.h197
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/PluginWrapper.h (renamed from libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h)33
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/RealTime.h46
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/hostguard.h69
-rw-r--r--libs/vamp-sdk/vamp-hostsdk/vamp-hostsdk.h53
-rw-r--r--libs/vamp-sdk/vamp-sdk/Plugin.h62
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginAdapter.h6
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginBase.h22
-rw-r--r--libs/vamp-sdk/vamp-sdk/RealTime.h5
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.h99
-rw-r--r--libs/vamp-sdk/vamp-sdk/plugguard.h98
-rw-r--r--libs/vamp-sdk/vamp-sdk/vamp-sdk.h46
-rw-r--r--libs/vamp-sdk/vamp/vamp.h57
31 files changed, 4127 insertions, 234 deletions
diff --git a/libs/vamp-sdk/SConscript b/libs/vamp-sdk/SConscript
index e2d602e157..907149765f 100644
--- a/libs/vamp-sdk/SConscript
+++ b/libs/vamp-sdk/SConscript
@@ -5,18 +5,17 @@ import os.path
import glob
vampsdk_files = Split ("""
-vamp-sdk/PluginAdapter.cpp
-vamp-sdk/RealTime.cpp
+src/vamp-sdk/PluginAdapter.cpp
+src/vamp-sdk/RealTime.cpp
""")
vamphostsdk_files = Split ("""
-vamp-sdk/PluginHostAdapter.cpp
-vamp-sdk/hostext/PluginBufferingAdapter.cpp
-vamp-sdk/hostext/PluginChannelAdapter.cpp
-vamp-sdk/hostext/PluginInputDomainAdapter.cpp
-vamp-sdk/hostext/PluginLoader.cpp
-vamp-sdk/hostext/PluginWrapper.cpp
-vamp-sdk/RealTime.cpp
+src/vamp-hostsdk/PluginHostAdapter.cpp
+src/vamp-hostsdk/PluginBufferingAdapter.cpp
+src/vamp-hostsdk/PluginChannelAdapter.cpp
+src/vamp-hostsdk/PluginInputDomainAdapter.cpp
+src/vamp-hostsdk/PluginLoader.cpp
+src/vamp-hostsdk/PluginWrapper.cpp
""")
Import('env install_prefix libraries')
@@ -43,4 +42,4 @@ env.Alias('tarball', env.Distribute (env['DISTTREE'],
vamphostsdk_files +
glob.glob('vamp/*.h') +
glob.glob('vamp-sdk/*.h') +
- glob.glob('vamp-sdk/hostext/*.h')))
+ glob.glob('vamp-hostsdk/*.h')))
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp
index cbe179fb6b..0aa92d9efc 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.cpp
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp
@@ -7,7 +7,7 @@
Centre for Digital Music, Queen Mary, University of London.
Copyright 2006-2007 Chris Cannam and QMUL.
- This file by Mark Levy and Chris Cannam.
+ This file by Mark Levy and Chris Cannam, Copyright 2007-2008 QMUL.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -38,11 +38,13 @@
#include <vector>
#include <map>
-#include "PluginBufferingAdapter.h"
+#include <vamp-hostsdk/PluginBufferingAdapter.h>
using std::vector;
using std::map;
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginBufferingAdapter.cpp)
+
namespace Vamp {
namespace HostExt {
@@ -52,11 +54,19 @@ class PluginBufferingAdapter::Impl
public:
Impl(Plugin *plugin, float inputSampleRate);
~Impl();
-
+
+ void setPluginStepSize(size_t stepSize);
+ void setPluginBlockSize(size_t blockSize);
+
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+ void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize);
+
OutputList getOutputDescriptors() const;
+ void setParameter(std::string, float);
+ void selectProgram(std::string);
+
void reset();
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
@@ -219,19 +229,22 @@ protected:
};
Plugin *m_plugin;
- size_t m_inputStepSize;
- size_t m_inputBlockSize;
- size_t m_stepSize;
- size_t m_blockSize;
+ size_t m_inputStepSize; // value passed to wrapper initialise()
+ size_t m_inputBlockSize; // value passed to wrapper initialise()
+ size_t m_setStepSize; // value passed to setPluginStepSize()
+ size_t m_setBlockSize; // value passed to setPluginBlockSize()
+ size_t m_stepSize; // value actually used to initialise plugin
+ size_t m_blockSize; // value actually used to initialise plugin
size_t m_channels;
vector<RingBuffer *> m_queue;
float **m_buffers;
float m_inputSampleRate;
- RealTime m_timestamp;
+ long m_frame;
bool m_unrun;
- OutputList m_outputs;
+ mutable OutputList m_outputs;
+ mutable std::map<int, bool> m_rewriteOutputTimes;
- void processBlock(FeatureSet& allFeatureSets, RealTime timestamp);
+ void processBlock(FeatureSet& allFeatureSets);
};
PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
@@ -244,6 +257,49 @@ PluginBufferingAdapter::~PluginBufferingAdapter()
{
delete m_impl;
}
+
+size_t
+PluginBufferingAdapter::getPreferredStepSize() const
+{
+ return getPreferredBlockSize();
+}
+
+size_t
+PluginBufferingAdapter::getPreferredBlockSize() const
+{
+ return PluginWrapper::getPreferredBlockSize();
+}
+
+size_t
+PluginBufferingAdapter::getPluginPreferredStepSize() const
+{
+ return PluginWrapper::getPreferredStepSize();
+}
+
+size_t
+PluginBufferingAdapter::getPluginPreferredBlockSize() const
+{
+ return PluginWrapper::getPreferredBlockSize();
+}
+
+void
+PluginBufferingAdapter::setPluginStepSize(size_t stepSize)
+{
+ m_impl->setPluginStepSize(stepSize);
+}
+
+void
+PluginBufferingAdapter::setPluginBlockSize(size_t blockSize)
+{
+ m_impl->setPluginBlockSize(blockSize);
+}
+
+void
+PluginBufferingAdapter::getActualStepAndBlockSizes(size_t &stepSize,
+ size_t &blockSize)
+{
+ m_impl->getActualStepAndBlockSizes(stepSize, blockSize);
+}
bool
PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
@@ -258,6 +314,18 @@ PluginBufferingAdapter::getOutputDescriptors() const
}
void
+PluginBufferingAdapter::setParameter(std::string name, float value)
+{
+ m_impl->setParameter(name, value);
+}
+
+void
+PluginBufferingAdapter::selectProgram(std::string name)
+{
+ m_impl->selectProgram(name);
+}
+
+void
PluginBufferingAdapter::reset()
{
m_impl->reset();
@@ -280,16 +348,18 @@ PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
m_plugin(plugin),
m_inputStepSize(0),
m_inputBlockSize(0),
+ m_setStepSize(0),
+ m_setBlockSize(0),
m_stepSize(0),
m_blockSize(0),
m_channels(0),
m_queue(0),
m_buffers(0),
m_inputSampleRate(inputSampleRate),
- m_timestamp(RealTime::zeroTime),
+ m_frame(0),
m_unrun(true)
{
- m_outputs = plugin->getOutputDescriptors();
+ (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes
}
PluginBufferingAdapter::Impl::~Impl()
@@ -302,13 +372,35 @@ PluginBufferingAdapter::Impl::~Impl()
}
delete[] m_buffers;
}
-
-size_t
-PluginBufferingAdapter::getPreferredStepSize() const
+
+void
+PluginBufferingAdapter::Impl::setPluginStepSize(size_t stepSize)
{
- return getPreferredBlockSize();
+ if (m_inputStepSize != 0) {
+ std::cerr << "PluginBufferingAdapter::setPluginStepSize: ERROR: Cannot be called after initialise()" << std::endl;
+ return;
+ }
+ m_setStepSize = stepSize;
}
+void
+PluginBufferingAdapter::Impl::setPluginBlockSize(size_t blockSize)
+{
+ if (m_inputBlockSize != 0) {
+ std::cerr << "PluginBufferingAdapter::setPluginBlockSize: ERROR: Cannot be called after initialise()" << std::endl;
+ return;
+ }
+ m_setBlockSize = blockSize;
+}
+
+void
+PluginBufferingAdapter::Impl::getActualStepAndBlockSizes(size_t &stepSize,
+ size_t &blockSize)
+{
+ stepSize = m_stepSize;
+ blockSize = m_blockSize;
+}
+
bool
PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
@@ -320,37 +412,64 @@ PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_
m_channels = channels;
m_inputStepSize = stepSize;
m_inputBlockSize = blockSize;
+
+ // if the user has requested particular step or block sizes, use
+ // those; otherwise use the step and block sizes which the plugin
+ // prefers
+
+ m_stepSize = 0;
+ m_blockSize = 0;
+
+ if (m_setStepSize > 0) {
+ m_stepSize = m_setStepSize;
+ }
+ if (m_setBlockSize > 0) {
+ m_blockSize = m_setBlockSize;
+ }
+
+ if (m_stepSize == 0 && m_blockSize == 0) {
+ m_stepSize = m_plugin->getPreferredStepSize();
+ m_blockSize = m_plugin->getPreferredBlockSize();
+ }
- // use the step and block sizes which the plugin prefers
- m_stepSize = m_plugin->getPreferredStepSize();
- m_blockSize = m_plugin->getPreferredBlockSize();
+ bool freq = (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain);
// or sensible defaults if it has no preference
if (m_blockSize == 0) {
- m_blockSize = 1024;
- }
- if (m_stepSize == 0) {
- if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
- m_stepSize = m_blockSize/2;
- } else {
- m_stepSize = m_blockSize;
- }
- } else if (m_stepSize > m_blockSize) {
- if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
+ if (m_stepSize == 0) {
+ m_blockSize = 1024;
+ if (freq) {
+ m_stepSize = m_blockSize / 2;
+ } else {
+ m_stepSize = m_blockSize;
+ }
+ } else if (freq) {
m_blockSize = m_stepSize * 2;
} else {
m_blockSize = m_stepSize;
}
+ } else if (m_stepSize == 0) { // m_blockSize != 0 (that was handled above)
+ if (freq) {
+ m_stepSize = m_blockSize/2;
+ } else {
+ m_stepSize = m_blockSize;
+ }
}
- // std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize
- // << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
-
// current implementation breaks if step is greater than block
if (m_stepSize > m_blockSize) {
- std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl;
- return false;
+ size_t newBlockSize;
+ if (freq) {
+ newBlockSize = m_stepSize * 2;
+ } else {
+ newBlockSize = m_stepSize;
+ }
+ std::cerr << "PluginBufferingAdapter::initialise: WARNING: step size " << m_stepSize << " is greater than block size " << m_blockSize << ": cannot handle this in adapter; adjusting block size to " << newBlockSize << std::endl;
+ m_blockSize = newBlockSize;
}
+
+// std::cerr << "PluginBufferingAdapter::initialise: NOTE: stepSize " << m_inputStepSize << " -> " << m_stepSize
+// << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
m_buffers = new float *[m_channels];
@@ -359,41 +478,108 @@ PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_
m_buffers[i] = new float[m_blockSize];
}
- return m_plugin->initialise(m_channels, m_stepSize, m_blockSize);
+ bool success = m_plugin->initialise(m_channels, m_stepSize, m_blockSize);
+
+// std::cerr << "PluginBufferingAdapter::initialise: success = " << success << std::endl;
+
+ if (success) {
+ // Re-query outputs; properties such as bin count may have
+ // changed on initialise
+ m_outputs.clear();
+ (void)getOutputDescriptors();
+ }
+
+ return success;
}
PluginBufferingAdapter::OutputList
PluginBufferingAdapter::Impl::getOutputDescriptors() const
{
- OutputList outs = m_plugin->getOutputDescriptors();
+ if (m_outputs.empty()) {
+// std::cerr << "PluginBufferingAdapter::getOutputDescriptors: querying anew" << std::endl;
+
+ m_outputs = m_plugin->getOutputDescriptors();
+ }
+
+ PluginBufferingAdapter::OutputList outs = m_outputs;
+
for (size_t i = 0; i < outs.size(); ++i) {
- if (outs[i].sampleType == OutputDescriptor::OneSamplePerStep) {
- outs[i].sampleRate = 1.f / m_stepSize;
+
+ switch (outs[i].sampleType) {
+
+ case OutputDescriptor::OneSamplePerStep:
+ outs[i].sampleType = OutputDescriptor::FixedSampleRate;
+ outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
+ m_rewriteOutputTimes[i] = true;
+ break;
+
+ case OutputDescriptor::FixedSampleRate:
+ if (outs[i].sampleRate == 0.f) {
+ outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
+ }
+ // We actually only need to rewrite output times for
+ // features that don't have timestamps already, but we
+ // can't tell from here whether our features will have
+ // timestamps or not
+ m_rewriteOutputTimes[i] = true;
+ break;
+
+ case OutputDescriptor::VariableSampleRate:
+ m_rewriteOutputTimes[i] = false;
+ break;
}
- outs[i].sampleType = OutputDescriptor::VariableSampleRate;
}
+
return outs;
}
void
+PluginBufferingAdapter::Impl::setParameter(std::string name, float value)
+{
+ m_plugin->setParameter(name, value);
+
+ // Re-query outputs; properties such as bin count may have changed
+ m_outputs.clear();
+ (void)getOutputDescriptors();
+}
+
+void
+PluginBufferingAdapter::Impl::selectProgram(std::string name)
+{
+ m_plugin->selectProgram(name);
+
+ // Re-query outputs; properties such as bin count may have changed
+ m_outputs.clear();
+ (void)getOutputDescriptors();
+}
+
+void
PluginBufferingAdapter::Impl::reset()
{
- m_timestamp = RealTime::zeroTime;
+ m_frame = 0;
m_unrun = true;
for (size_t i = 0; i < m_queue.size(); ++i) {
m_queue[i]->reset();
}
+
+ m_plugin->reset();
}
PluginBufferingAdapter::FeatureSet
PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
RealTime timestamp)
{
+ if (m_inputStepSize == 0) {
+ std::cerr << "PluginBufferingAdapter::process: ERROR: Plugin has not been initialised" << std::endl;
+ return FeatureSet();
+ }
+
FeatureSet allFeatureSets;
if (m_unrun) {
- m_timestamp = timestamp;
+ m_frame = RealTime::realTime2Frame(timestamp,
+ int(m_inputSampleRate + 0.5));
m_unrun = false;
}
@@ -414,7 +600,7 @@ PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
// process as much as we can
while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
- processBlock(allFeatureSets, timestamp);
+ processBlock(allFeatureSets);
}
return allFeatureSets;
@@ -427,7 +613,7 @@ PluginBufferingAdapter::Impl::getRemainingFeatures()
// process remaining samples in queue
while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
- processBlock(allFeatureSets, m_timestamp);
+ processBlock(allFeatureSets);
}
// pad any last samples remaining and process
@@ -435,7 +621,7 @@ PluginBufferingAdapter::Impl::getRemainingFeatures()
for (size_t i = 0; i < m_channels; ++i) {
m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
}
- processBlock(allFeatureSets, m_timestamp);
+ processBlock(allFeatureSets);
}
// get remaining features
@@ -454,44 +640,58 @@ PluginBufferingAdapter::Impl::getRemainingFeatures()
}
void
-PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets,
- RealTime timestamp)
+PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
{
for (size_t i = 0; i < m_channels; ++i) {
m_queue[i]->peek(m_buffers[i], m_blockSize);
}
- FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp);
+ long frame = m_frame;
+ RealTime timestamp = RealTime::frame2RealTime
+ (frame, int(m_inputSampleRate + 0.5));
+
+ FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
- for (map<int, FeatureList>::iterator iter = featureSet.begin();
+ for (FeatureSet::iterator iter = featureSet.begin();
iter != featureSet.end(); ++iter) {
-
- FeatureList featureList = iter->second;
+
int outputNo = iter->first;
-
- for (size_t i = 0; i < featureList.size(); ++i) {
+
+ if (m_rewriteOutputTimes[outputNo]) {
- // make sure the timestamp is set
- switch (m_outputs[outputNo].sampleType) {
+ FeatureList featureList = iter->second;
+
+ for (size_t i = 0; i < featureList.size(); ++i) {
- case OutputDescriptor::OneSamplePerStep:
- // use our internal timestamp - OK????
- featureList[i].timestamp = m_timestamp;
- break;
+ switch (m_outputs[outputNo].sampleType) {
- case OutputDescriptor::FixedSampleRate:
- // use our internal timestamp
- featureList[i].timestamp = m_timestamp;
- break;
+ case OutputDescriptor::OneSamplePerStep:
+ // use our internal timestamp, always
+ featureList[i].timestamp = timestamp;
+ featureList[i].hasTimestamp = true;
+ break;
- case OutputDescriptor::VariableSampleRate:
- break; // plugin must set timestamp
+ case OutputDescriptor::FixedSampleRate:
+ // use our internal timestamp if feature lacks one
+ if (!featureList[i].hasTimestamp) {
+ featureList[i].timestamp = timestamp;
+ featureList[i].hasTimestamp = true;
+ }
+ break;
- default:
- break;
- }
+ case OutputDescriptor::VariableSampleRate:
+ break; // plugin must set timestamp
+
+ default:
+ break;
+ }
- allFeatureSets[outputNo].push_back(featureList[i]);
+ allFeatureSets[outputNo].push_back(featureList[i]);
+ }
+ } else {
+ for (size_t i = 0; i < iter->second.size(); ++i) {
+ allFeatureSets[outputNo].push_back(iter->second[i]);
+ }
}
}
@@ -501,16 +701,12 @@ PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets,
m_queue[i]->skip(m_stepSize);
}
- // fake up the timestamp each time we step forward
-
- long frame = RealTime::realTime2Frame(m_timestamp,
- int(m_inputSampleRate + 0.5));
- m_timestamp = RealTime::frame2RealTime(frame + m_stepSize,
- int(m_inputSampleRate + 0.5));
+ // increment internal frame counter each time we step forward
+ m_frame += m_stepSize;
}
}
}
-
+_VAMP_SDK_HOSTSPACE_END(PluginBufferingAdapter.cpp)
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginChannelAdapter.cpp
index fe676bcafd..92a35bba85 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginChannelAdapter.cpp
@@ -34,7 +34,9 @@
authorization.
*/
-#include "PluginChannelAdapter.h"
+#include <vamp-hostsdk/PluginChannelAdapter.h>
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginChannelAdapter.cpp)
namespace Vamp {
@@ -49,6 +51,7 @@ public:
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+ FeatureSet processInterleaved(const float *inputBuffers, RealTime timestamp);
protected:
Plugin *m_plugin;
@@ -56,6 +59,7 @@ protected:
size_t m_inputChannels;
size_t m_pluginChannels;
float **m_buffer;
+ float **m_deinterleave;
const float **m_forwardPtrs;
};
@@ -83,12 +87,20 @@ PluginChannelAdapter::process(const float *const *inputBuffers,
return m_impl->process(inputBuffers, timestamp);
}
+PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::processInterleaved(const float *inputBuffers,
+ RealTime timestamp)
+{
+ return m_impl->processInterleaved(inputBuffers, timestamp);
+}
+
PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
m_plugin(plugin),
m_blockSize(0),
m_inputChannels(0),
m_pluginChannels(0),
m_buffer(0),
+ m_deinterleave(0),
m_forwardPtrs(0)
{
}
@@ -109,6 +121,14 @@ PluginChannelAdapter::Impl::~Impl()
m_buffer = 0;
}
+ if (m_deinterleave) {
+ for (size_t i = 0; i < m_inputChannels; ++i) {
+ delete[] m_deinterleave[i];
+ }
+ delete[] m_deinterleave;
+ m_deinterleave = 0;
+ }
+
if (m_forwardPtrs) {
delete[] m_forwardPtrs;
m_forwardPtrs = 0;
@@ -143,7 +163,7 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
m_pluginChannels = minch;
- // std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+// std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
} else if (m_inputChannels > maxch) {
@@ -155,18 +175,18 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
m_buffer = new float *[1];
m_buffer[0] = new float[blockSize];
- // std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
+// std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
} else {
- // std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+// std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
}
m_pluginChannels = maxch;
} else {
- // std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
+// std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
m_pluginChannels = m_inputChannels;
}
@@ -174,6 +194,26 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
}
PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers,
+ RealTime timestamp)
+{
+ if (!m_deinterleave) {
+ m_deinterleave = new float *[m_inputChannels];
+ for (size_t i = 0; i < m_inputChannels; ++i) {
+ m_deinterleave[i] = new float[m_blockSize];
+ }
+ }
+
+ for (size_t i = 0; i < m_inputChannels; ++i) {
+ for (size_t j = 0; j < m_blockSize; ++j) {
+ m_deinterleave[i][j] = inputBuffers[j * m_inputChannels + i];
+ }
+ }
+
+ return process(m_deinterleave, timestamp);
+}
+
+PluginChannelAdapter::FeatureSet
PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
RealTime timestamp)
{
@@ -225,4 +265,6 @@ PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
}
+_VAMP_SDK_HOSTSPACE_END(PluginChannelAdapter.cpp)
+
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/PluginHostAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginHostAdapter.cpp
new file mode 100644
index 0000000000..5bf323b1a7
--- /dev/null
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginHostAdapter.cpp
@@ -0,0 +1,456 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include <vamp-hostsdk/PluginHostAdapter.h>
+#include <cstdlib>
+
+#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
+#error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
+#endif
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
+
+namespace Vamp
+{
+
+PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
+ float inputSampleRate) :
+ Plugin(inputSampleRate),
+ m_descriptor(descriptor)
+{
+// std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
+ m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
+ if (!m_handle) {
+// std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
+ }
+}
+
+PluginHostAdapter::~PluginHostAdapter()
+{
+// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
+ if (m_handle) m_descriptor->cleanup(m_handle);
+}
+
+std::vector<std::string>
+PluginHostAdapter::getPluginPath()
+{
+ std::vector<std::string> path;
+ std::string envPath;
+
+ char *cpath = getenv("VAMP_PATH");
+ if (cpath) envPath = cpath;
+
+#ifdef _WIN32
+#define PATH_SEPARATOR ';'
+#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
+#else
+#define PATH_SEPARATOR ':'
+#ifdef __APPLE__
+#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
+#else
+#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
+#endif
+#endif
+
+ if (envPath == "") {
+ envPath = DEFAULT_VAMP_PATH;
+ char *chome = getenv("HOME");
+ if (chome) {
+ std::string home(chome);
+ std::string::size_type f;
+ while ((f = envPath.find("$HOME")) != std::string::npos &&
+ f < envPath.length()) {
+ envPath.replace(f, 5, home);
+ }
+ }
+#ifdef _WIN32
+ char *cpfiles = getenv("ProgramFiles");
+ if (!cpfiles) cpfiles = (char *)"C:\\Program Files";
+ std::string pfiles(cpfiles);
+ std::string::size_type f;
+ while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
+ f < envPath.length()) {
+ envPath.replace(f, 14, pfiles);
+ }
+#endif
+ }
+
+ std::string::size_type index = 0, newindex = 0;
+
+ while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
+ path.push_back(envPath.substr(index, newindex - index));
+ index = newindex + 1;
+ }
+
+ path.push_back(envPath.substr(index));
+
+ return path;
+}
+
+bool
+PluginHostAdapter::initialise(size_t channels,
+ size_t stepSize,
+ size_t blockSize)
+{
+ if (!m_handle) return false;
+ return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
+ true : false;
+}
+
+void
+PluginHostAdapter::reset()
+{
+ if (!m_handle) {
+// std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
+ return;
+ }
+// std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
+ m_descriptor->reset(m_handle);
+}
+
+PluginHostAdapter::InputDomain
+PluginHostAdapter::getInputDomain() const
+{
+ if (m_descriptor->inputDomain == vampFrequencyDomain) {
+ return FrequencyDomain;
+ } else {
+ return TimeDomain;
+ }
+}
+
+unsigned int
+PluginHostAdapter::getVampApiVersion() const
+{
+ return m_descriptor->vampApiVersion;
+}
+
+std::string
+PluginHostAdapter::getIdentifier() const
+{
+ return m_descriptor->identifier;
+}
+
+std::string
+PluginHostAdapter::getName() const
+{
+ return m_descriptor->name;
+}
+
+std::string
+PluginHostAdapter::getDescription() const
+{
+ return m_descriptor->description;
+}
+
+std::string
+PluginHostAdapter::getMaker() const
+{
+ return m_descriptor->maker;
+}
+
+int
+PluginHostAdapter::getPluginVersion() const
+{
+ return m_descriptor->pluginVersion;
+}
+
+std::string
+PluginHostAdapter::getCopyright() const
+{
+ return m_descriptor->copyright;
+}
+
+PluginHostAdapter::ParameterList
+PluginHostAdapter::getParameterDescriptors() const
+{
+ ParameterList list;
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ const VampParameterDescriptor *spd = m_descriptor->parameters[i];
+ ParameterDescriptor pd;
+ pd.identifier = spd->identifier;
+ pd.name = spd->name;
+ pd.description = spd->description;
+ pd.unit = spd->unit;
+ pd.minValue = spd->minValue;
+ pd.maxValue = spd->maxValue;
+ pd.defaultValue = spd->defaultValue;
+ pd.isQuantized = spd->isQuantized;
+ pd.quantizeStep = spd->quantizeStep;
+ if (pd.isQuantized && spd->valueNames) {
+ for (unsigned int j = 0; spd->valueNames[j]; ++j) {
+ pd.valueNames.push_back(spd->valueNames[j]);
+ }
+ }
+ list.push_back(pd);
+ }
+ return list;
+}
+
+float
+PluginHostAdapter::getParameter(std::string param) const
+{
+ if (!m_handle) return 0.0;
+
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ if (param == m_descriptor->parameters[i]->identifier) {
+ return m_descriptor->getParameter(m_handle, i);
+ }
+ }
+
+ return 0.0;
+}
+
+void
+PluginHostAdapter::setParameter(std::string param,
+ float value)
+{
+ if (!m_handle) return;
+
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ if (param == m_descriptor->parameters[i]->identifier) {
+ m_descriptor->setParameter(m_handle, i, value);
+ return;
+ }
+ }
+}
+
+PluginHostAdapter::ProgramList
+PluginHostAdapter::getPrograms() const
+{
+ ProgramList list;
+
+ for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+ list.push_back(m_descriptor->programs[i]);
+ }
+
+ return list;
+}
+
+std::string
+PluginHostAdapter::getCurrentProgram() const
+{
+ if (!m_handle) return "";
+
+ int pn = m_descriptor->getCurrentProgram(m_handle);
+ return m_descriptor->programs[pn];
+}
+
+void
+PluginHostAdapter::selectProgram(std::string program)
+{
+ if (!m_handle) return;
+
+ for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+ if (program == m_descriptor->programs[i]) {
+ m_descriptor->selectProgram(m_handle, i);
+ return;
+ }
+ }
+}
+
+size_t
+PluginHostAdapter::getPreferredStepSize() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getPreferredStepSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getPreferredBlockSize() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getPreferredBlockSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMinChannelCount() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getMinChannelCount(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMaxChannelCount() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getMaxChannelCount(m_handle);
+}
+
+PluginHostAdapter::OutputList
+PluginHostAdapter::getOutputDescriptors() const
+{
+ OutputList list;
+ if (!m_handle) {
+// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
+ return list;
+ }
+
+ unsigned int count = m_descriptor->getOutputCount(m_handle);
+
+ for (unsigned int i = 0; i < count; ++i) {
+ VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
+ OutputDescriptor d;
+ d.identifier = sd->identifier;
+ d.name = sd->name;
+ d.description = sd->description;
+ d.unit = sd->unit;
+ d.hasFixedBinCount = sd->hasFixedBinCount;
+ d.binCount = sd->binCount;
+ if (d.hasFixedBinCount && sd->binNames) {
+ for (unsigned int j = 0; j < sd->binCount; ++j) {
+ d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
+ }
+ }
+ d.hasKnownExtents = sd->hasKnownExtents;
+ d.minValue = sd->minValue;
+ d.maxValue = sd->maxValue;
+ d.isQuantized = sd->isQuantized;
+ d.quantizeStep = sd->quantizeStep;
+
+ switch (sd->sampleType) {
+ case vampOneSamplePerStep:
+ d.sampleType = OutputDescriptor::OneSamplePerStep; break;
+ case vampFixedSampleRate:
+ d.sampleType = OutputDescriptor::FixedSampleRate; break;
+ case vampVariableSampleRate:
+ d.sampleType = OutputDescriptor::VariableSampleRate; break;
+ }
+
+ d.sampleRate = sd->sampleRate;
+
+ if (m_descriptor->vampApiVersion >= 2) {
+ d.hasDuration = sd->hasDuration;
+ } else {
+ d.hasDuration = false;
+ }
+
+ list.push_back(d);
+
+ m_descriptor->releaseOutputDescriptor(sd);
+ }
+
+ return list;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+ FeatureSet fs;
+ if (!m_handle) return fs;
+
+ int sec = timestamp.sec;
+ int nsec = timestamp.nsec;
+
+ VampFeatureList *features = m_descriptor->process(m_handle,
+ inputBuffers,
+ sec, nsec);
+
+ convertFeatures(features, fs);
+ m_descriptor->releaseFeatureSet(features);
+ return fs;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::getRemainingFeatures()
+{
+ FeatureSet fs;
+ if (!m_handle) return fs;
+
+ VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
+
+ convertFeatures(features, fs);
+ m_descriptor->releaseFeatureSet(features);
+ return fs;
+}
+
+void
+PluginHostAdapter::convertFeatures(VampFeatureList *features,
+ FeatureSet &fs)
+{
+ if (!features) return;
+
+ unsigned int outputs = m_descriptor->getOutputCount(m_handle);
+
+ for (unsigned int i = 0; i < outputs; ++i) {
+
+ VampFeatureList &list = features[i];
+
+ if (list.featureCount > 0) {
+
+ Feature feature;
+ feature.values.reserve(list.features[0].v1.valueCount);
+
+ for (unsigned int j = 0; j < list.featureCount; ++j) {
+
+ feature.hasTimestamp = list.features[j].v1.hasTimestamp;
+ feature.timestamp = RealTime(list.features[j].v1.sec,
+ list.features[j].v1.nsec);
+ feature.hasDuration = false;
+
+ if (m_descriptor->vampApiVersion >= 2) {
+ unsigned int j2 = j + list.featureCount;
+ feature.hasDuration = list.features[j2].v2.hasDuration;
+ feature.duration = RealTime(list.features[j2].v2.durationSec,
+ list.features[j2].v2.durationNsec);
+ }
+
+ for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
+ feature.values.push_back(list.features[j].v1.values[k]);
+ }
+
+ if (list.features[j].v1.label) {
+ feature.label = list.features[j].v1.label;
+ }
+
+ fs[i].push_back(feature);
+
+ if (list.features[j].v1.valueCount > 0) {
+ feature.values.clear();
+ }
+
+ if (list.features[j].v1.label) {
+ feature.label = "";
+ }
+ }
+ }
+ }
+}
+
+}
+
+_VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginInputDomainAdapter.cpp
index 273925f96d..967d5cfcd9 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginInputDomainAdapter.cpp
@@ -37,10 +37,11 @@
authorization.
*/
-#include "PluginInputDomainAdapter.h"
+#include <vamp-hostsdk/PluginInputDomainAdapter.h>
#include <cmath>
+
/**
* If you want to compile using FFTW instead of the built-in FFT
* implementation for the PluginInputDomainAdapter, define HAVE_FFTW3
@@ -68,6 +69,9 @@
#include <fftw3.h>
#endif
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
+
namespace Vamp {
namespace HostExt {
@@ -84,6 +88,8 @@ public:
size_t getPreferredBlockSize() const;
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+ RealTime getTimestampAdjustment() const;
protected:
Plugin *m_plugin;
@@ -149,6 +155,13 @@ PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime tim
return m_impl->process(inputBuffers, timestamp);
}
+RealTime
+PluginInputDomainAdapter::getTimestampAdjustment() const
+{
+ return m_impl->getTimestampAdjustment();
+}
+
+
PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
m_plugin(plugin),
m_inputSampleRate(inputSampleRate),
@@ -336,6 +349,17 @@ PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
return blockSize;
}
+RealTime
+PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
+{
+ if (m_plugin->getInputDomain() == TimeDomain) {
+ return RealTime::zeroTime;
+ } else {
+ return RealTime::frame2RealTime
+ (m_blockSize/2, int(m_inputSampleRate + 0.5));
+ }
+}
+
Plugin::FeatureSet
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
RealTime timestamp)
@@ -388,8 +412,7 @@ PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
- timestamp = timestamp + RealTime::frame2RealTime
- (m_blockSize/2, int(m_inputSampleRate + 0.5));
+ timestamp = timestamp + getTimestampAdjustment();
// std::cerr << " to " << timestamp << std::endl;
@@ -555,3 +578,5 @@ PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse,
}
+_VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp
index e9d75ee181..3bf23bb165 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp
@@ -34,16 +34,15 @@
authorization.
*/
-#include "vamp-sdk/PluginHostAdapter.h"
-#include "PluginLoader.h"
-#include "PluginInputDomainAdapter.h"
-#include "PluginChannelAdapter.h"
-#include "PluginBufferingAdapter.h"
+#include <vamp-hostsdk/PluginHostAdapter.h>
+#include <vamp-hostsdk/PluginLoader.h>
+#include <vamp-hostsdk/PluginInputDomainAdapter.h>
+#include <vamp-hostsdk/PluginChannelAdapter.h>
+#include <vamp-hostsdk/PluginBufferingAdapter.h>
-#include <string>
-#include <cstring>
#include <fstream>
#include <cctype> // tolower
+
#include <cstring>
#ifdef _WIN32
@@ -67,6 +66,8 @@
using namespace std;
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.cpp)
+
namespace Vamp {
namespace HostExt {
@@ -518,7 +519,7 @@ PluginLoader::Impl::loadLibrary(string path)
<< path << "\"" << endl;
}
#else
- handle = dlopen(path.c_str(), RTLD_LAZY);
+ handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle) {
cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
<< path << "\": " << dlerror() << endl;
@@ -586,8 +587,6 @@ PluginLoader::Impl::listFiles(string dir, string extension)
struct dirent *e = 0;
while ((e = readdir(d))) {
- if (!(e->d_type & DT_REG) && (e->d_type != DT_UNKNOWN)) continue;
-
if (!e->d_name) continue;
size_t len = strlen(e->d_name);
@@ -637,3 +636,6 @@ PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
}
}
+
+_VAMP_SDK_HOSTSPACE_END(PluginLoader.cpp)
+
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp
new file mode 100644
index 0000000000..592190fdf4
--- /dev/null
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp
@@ -0,0 +1,952 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2008 Chris Cannam and QMUL.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include <vamp-hostsdk/PluginSummarisingAdapter.h>
+
+#include <map>
+#include <algorithm>
+#include <cmath>
+#include <climits>
+
+//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1
+//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT 1
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter.cpp)
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginSummarisingAdapter::Impl
+{
+public:
+ Impl(Plugin *plugin, float inputSampleRate);
+ ~Impl();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ void reset();
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+ FeatureSet getRemainingFeatures();
+
+ void setSummarySegmentBoundaries(const SegmentBoundaries &);
+
+ FeatureList getSummaryForOutput(int output,
+ SummaryType type,
+ AveragingMethod avg);
+
+ FeatureSet getSummaryForAllOutputs(SummaryType type,
+ AveragingMethod avg);
+
+protected:
+ Plugin *m_plugin;
+ float m_inputSampleRate;
+ size_t m_stepSize;
+ size_t m_blockSize;
+
+ SegmentBoundaries m_boundaries;
+
+ typedef std::vector<float> ValueList;
+
+ struct Result { // smaller than Feature
+ RealTime time;
+ RealTime duration;
+ ValueList values; // bin number -> value
+ };
+
+ typedef std::vector<Result> ResultList;
+
+ struct OutputAccumulator {
+ int bins;
+ ResultList results;
+ OutputAccumulator() : bins(0) { }
+ };
+
+ typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
+ OutputAccumulatorMap m_accumulators; // output number -> accumulator
+
+ typedef std::map<RealTime, OutputAccumulator> SegmentAccumulatorMap;
+ typedef std::map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap;
+ OutputSegmentAccumulatorMap m_segmentedAccumulators; // output -> segmented
+
+ typedef std::map<int, RealTime> OutputTimestampMap;
+ OutputTimestampMap m_prevTimestamps; // output number -> timestamp
+ OutputTimestampMap m_prevDurations; // output number -> durations
+
+ struct OutputBinSummary {
+
+ int count;
+
+ // extents
+ double minimum;
+ double maximum;
+ double sum;
+
+ // sample-average results
+ double median;
+ double mode;
+ double variance;
+
+ // continuous-time average results
+ double median_c;
+ double mode_c;
+ double mean_c;
+ double variance_c;
+ };
+
+ typedef std::map<int, OutputBinSummary> OutputSummary;
+ typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
+ typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
+
+ OutputSummarySegmentMap m_summaries;
+
+ bool m_reduced;
+ RealTime m_endTime;
+
+ void accumulate(const FeatureSet &fs, RealTime, bool final);
+ void accumulate(int output, const Feature &f, RealTime, bool final);
+ void accumulateFinalDurations();
+ void findSegmentBounds(RealTime t, RealTime &start, RealTime &end);
+ void segment();
+ void reduce();
+
+ std::string getSummaryLabel(SummaryType type, AveragingMethod avg);
+};
+
+static RealTime INVALID_DURATION(INT_MIN, INT_MIN);
+
+PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
+ PluginWrapper(plugin)
+{
+ m_impl = new Impl(plugin, m_inputSampleRate);
+}
+
+PluginSummarisingAdapter::~PluginSummarisingAdapter()
+{
+ delete m_impl;
+}
+
+bool
+PluginSummarisingAdapter::initialise(size_t channels,
+ size_t stepSize, size_t blockSize)
+{
+ return
+ PluginWrapper::initialise(channels, stepSize, blockSize) &&
+ m_impl->initialise(channels, stepSize, blockSize);
+}
+
+void
+PluginSummarisingAdapter::reset()
+{
+ m_impl->reset();
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
+{
+ return m_impl->process(inputBuffers, timestamp);
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::getRemainingFeatures()
+{
+ return m_impl->getRemainingFeatures();
+}
+
+void
+PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries &b)
+{
+ m_impl->setSummarySegmentBoundaries(b);
+}
+
+Plugin::FeatureList
+PluginSummarisingAdapter::getSummaryForOutput(int output,
+ SummaryType type,
+ AveragingMethod avg)
+{
+ return m_impl->getSummaryForOutput(output, type, avg);
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type,
+ AveragingMethod avg)
+{
+ return m_impl->getSummaryForAllOutputs(type, avg);
+}
+
+PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
+ m_plugin(plugin),
+ m_inputSampleRate(inputSampleRate),
+ m_reduced(false)
+{
+}
+
+PluginSummarisingAdapter::Impl::~Impl()
+{
+}
+
+bool
+PluginSummarisingAdapter::Impl::initialise(size_t channels,
+ size_t stepSize, size_t blockSize)
+{
+ m_stepSize = stepSize;
+ m_blockSize = blockSize;
+ return true;
+}
+
+void
+PluginSummarisingAdapter::Impl::reset()
+{
+ m_accumulators.clear();
+ m_segmentedAccumulators.clear();
+ m_prevTimestamps.clear();
+ m_prevDurations.clear();
+ m_summaries.clear();
+ m_reduced = false;
+ m_endTime = RealTime();
+ m_plugin->reset();
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+ if (m_reduced) {
+ std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
+ }
+ FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
+ accumulate(fs, timestamp, false);
+ m_endTime = timestamp +
+ RealTime::frame2RealTime(m_stepSize, int(m_inputSampleRate + 0.5));
+ return fs;
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::Impl::getRemainingFeatures()
+{
+ if (m_reduced) {
+ std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
+ }
+ FeatureSet fs = m_plugin->getRemainingFeatures();
+ accumulate(fs, m_endTime, true);
+ return fs;
+}
+
+void
+PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b)
+{
+ m_boundaries = b;
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl;
+ for (SegmentBoundaries::const_iterator i = m_boundaries.begin();
+ i != m_boundaries.end(); ++i) {
+ std::cerr << *i << " ";
+ }
+ std::cerr << std::endl;
+#endif
+}
+
+Plugin::FeatureList
+PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
+ SummaryType type,
+ AveragingMethod avg)
+{
+ if (!m_reduced) {
+ accumulateFinalDurations();
+ segment();
+ reduce();
+ m_reduced = true;
+ }
+
+ bool continuous = (avg == ContinuousTimeAverage);
+
+ FeatureList fl;
+ for (SummarySegmentMap::const_iterator i = m_summaries[output].begin();
+ i != m_summaries[output].end(); ++i) {
+
+ Feature f;
+
+ f.hasTimestamp = true;
+ f.timestamp = i->first;
+
+ f.hasDuration = true;
+ SummarySegmentMap::const_iterator ii = i;
+ if (++ii == m_summaries[output].end()) {
+ f.duration = m_endTime - f.timestamp;
+ } else {
+ f.duration = ii->first - f.timestamp;
+ }
+
+ f.label = getSummaryLabel(type, avg);
+
+ for (OutputSummary::const_iterator j = i->second.begin();
+ j != i->second.end(); ++j) {
+
+ // these will be ordered by bin number, and no bin numbers
+ // will be missing except at the end (because of the way
+ // the accumulators were initially filled in accumulate())
+
+ const OutputBinSummary &summary = j->second;
+ double result = 0.f;
+
+ switch (type) {
+
+ case Minimum:
+ result = summary.minimum;
+ break;
+
+ case Maximum:
+ result = summary.maximum;
+ break;
+
+ case Mean:
+ if (continuous) {
+ result = summary.mean_c;
+ } else if (summary.count) {
+ result = summary.sum / summary.count;
+ }
+ break;
+
+ case Median:
+ if (continuous) result = summary.median_c;
+ else result = summary.median;
+ break;
+
+ case Mode:
+ if (continuous) result = summary.mode_c;
+ else result = summary.mode;
+ break;
+
+ case Sum:
+ result = summary.sum;
+ break;
+
+ case Variance:
+ if (continuous) result = summary.variance_c;
+ else result = summary.variance;
+ break;
+
+ case StandardDeviation:
+ if (continuous) result = sqrtf(summary.variance_c);
+ else result = sqrtf(summary.variance);
+ break;
+
+ case Count:
+ result = summary.count;
+ break;
+
+ case UnknownSummaryType:
+ break;
+
+ default:
+ break;
+ }
+
+ f.values.push_back(result);
+ }
+
+ fl.push_back(f);
+ }
+ return fl;
+}
+
+Plugin::FeatureSet
+PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
+ AveragingMethod avg)
+{
+ if (!m_reduced) {
+ accumulateFinalDurations();
+ segment();
+ reduce();
+ m_reduced = true;
+ }
+
+ FeatureSet fs;
+ for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin();
+ i != m_summaries.end(); ++i) {
+ fs[i->first] = getSummaryForOutput(i->first, type, avg);
+ }
+ return fs;
+}
+
+void
+PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
+ RealTime timestamp,
+ bool final)
+{
+ for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
+ for (FeatureList::const_iterator j = i->second.begin();
+ j != i->second.end(); ++j) {
+ if (j->hasTimestamp) {
+ accumulate(i->first, *j, j->timestamp, final);
+ } else {
+ //!!! is this correct?
+ accumulate(i->first, *j, timestamp, final);
+ }
+ }
+ }
+}
+
+std::string
+PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type,
+ AveragingMethod avg)
+{
+ std::string label;
+ std::string avglabel;
+
+ if (avg == SampleAverage) avglabel = ", sample average";
+ else avglabel = ", continuous-time average";
+
+ switch (type) {
+ case Minimum: label = "(minimum value)"; break;
+ case Maximum: label = "(maximum value)"; break;
+ case Mean: label = "(mean value" + avglabel + ")"; break;
+ case Median: label = "(median value" + avglabel + ")"; break;
+ case Mode: label = "(modal value" + avglabel + ")"; break;
+ case Sum: label = "(sum)"; break;
+ case Variance: label = "(variance" + avglabel + ")"; break;
+ case StandardDeviation: label = "(standard deviation" + avglabel + ")"; break;
+ case Count: label = "(count)"; break;
+ case UnknownSummaryType: label = "(unknown summary)"; break;
+ }
+
+ return label;
+}
+
+void
+PluginSummarisingAdapter::Impl::accumulate(int output,
+ const Feature &f,
+ RealTime timestamp,
+ bool final)
+{
+ // What should happen if a feature's duration spans a segment
+ // boundary? I think we probably want to chop it, and pretend
+ // that it appears in both. A very long feature (e.g. key, if the
+ // whole audio is in a single key) might span many or all
+ // segments, and we want that to be reflected in the results
+ // (e.g. it is the modal key in all of those segments, not just
+ // the first). This is actually quite complicated to do.
+
+ // If features spanning a boundary should be chopped, then we need
+ // to have per-segment accumulators (and the feature value goes
+ // into both -- with a separate phase to split the accumulator up
+ // into segments).
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl;
+#endif
+
+ // At each process step, accumulate() is called once for each
+ // feature on each output within that process's returned feature
+ // list, and with the timestamp passed in being that of the start
+ // of the process block.
+
+ // At the end (in getRemainingFeatures), accumulate() is called
+ // once for each feature on each output within the feature list
+ // returned by getRemainingFeatures, and with the timestamp being
+ // the same as the last process block and final set to true.
+
+ // (What if getRemainingFeatures doesn't return any features? We
+ // still need to ensure that the final duration is written. Need
+ // a separate function to close the durations.)
+
+ // At each call, we pull out the value for the feature and stuff
+ // it into the accumulator's appropriate values array; and we
+ // calculate the duration for the _previous_ feature, or pull it
+ // from the prevDurations array if the previous feature had a
+ // duration in its structure, and stuff that into the
+ // accumulator's appropriate durations array.
+
+ if (m_prevDurations.find(output) != m_prevDurations.end()) {
+
+ // Not the first time accumulate has been called for this
+ // output -- there has been a previous feature
+
+ RealTime prevDuration;
+
+ // Note that m_prevDurations[output] only contains the
+ // duration field that was contained in the previous feature.
+ // If it didn't have an explicit duration,
+ // m_prevDurations[output] should be INVALID_DURATION and we
+ // will have to calculate the duration from the previous and
+ // current timestamps.
+
+ if (m_prevDurations[output] != INVALID_DURATION) {
+ prevDuration = m_prevDurations[output];
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl;
+#endif
+ } else {
+ prevDuration = timestamp - m_prevTimestamps[output];
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "Previous duration from diff: " << timestamp << " - "
+ << m_prevTimestamps[output] << std::endl;
+#endif
+ }
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "output " << output << ": ";
+ std::cerr << "Pushing previous duration as " << prevDuration << std::endl;
+#endif
+
+ m_accumulators[output].results
+ [m_accumulators[output].results.size() - 1]
+ .duration = prevDuration;
+ }
+
+ if (f.hasDuration) m_prevDurations[output] = f.duration;
+ else m_prevDurations[output] = INVALID_DURATION;
+
+ m_prevTimestamps[output] = timestamp;
+
+ if (f.hasDuration) {
+ RealTime et = timestamp;
+ et = et + f.duration;
+ if (et > m_endTime) m_endTime = et;
+ }
+
+ Result result;
+ result.time = timestamp;
+ result.duration = INVALID_DURATION;
+
+ if (int(f.values.size()) > m_accumulators[output].bins) {
+ m_accumulators[output].bins = f.values.size();
+ }
+
+ for (int i = 0; i < int(f.values.size()); ++i) {
+ result.values.push_back(f.values[i]);
+ }
+
+ m_accumulators[output].results.push_back(result);
+}
+
+void
+PluginSummarisingAdapter::Impl::accumulateFinalDurations()
+{
+ for (OutputTimestampMap::iterator i = m_prevTimestamps.begin();
+ i != m_prevTimestamps.end(); ++i) {
+
+ int output = i->first;
+
+ int acount = m_accumulators[output].results.size();
+
+ if (acount == 0) continue;
+
+ RealTime prevTimestamp = i->second;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "output " << output << ": ";
+#endif
+
+ if (m_prevDurations.find(output) != m_prevDurations.end() &&
+ m_prevDurations[output] != INVALID_DURATION) {
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl;
+#endif
+
+ m_accumulators[output].results[acount - 1].duration =
+ m_prevDurations[output];
+
+ } else {
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "Pushing final duration from diff as " << m_endTime << " - " << m_prevTimestamps[output] << std::endl;
+#endif
+
+ m_accumulators[output].results[acount - 1].duration =
+ m_endTime - m_prevTimestamps[output];
+ }
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "so duration for result no " << acount-1 << " is "
+ << m_accumulators[output].results[acount-1].duration
+ << std::endl;
+#endif
+ }
+}
+
+void
+PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t,
+ RealTime &start,
+ RealTime &end)
+{
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "findSegmentBounds: t = " << t << std::endl;
+#endif
+
+ SegmentBoundaries::const_iterator i = std::upper_bound
+ (m_boundaries.begin(), m_boundaries.end(), t);
+
+ start = RealTime::zeroTime;
+ end = m_endTime;
+
+ if (i != m_boundaries.end()) {
+ end = *i;
+ }
+
+ if (i != m_boundaries.begin()) {
+ start = *--i;
+ }
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl;
+#endif
+}
+
+void
+PluginSummarisingAdapter::Impl::segment()
+{
+ SegmentBoundaries::iterator boundaryitr = m_boundaries.begin();
+ RealTime segmentStart = RealTime::zeroTime;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "segment: starting" << std::endl;
+#endif
+
+ for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
+ i != m_accumulators.end(); ++i) {
+
+ int output = i->first;
+ OutputAccumulator &source = i->second;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "segment: total results for output " << output << " = "
+ << source.results.size() << std::endl;
+#endif
+
+ // This is basically nonsense if the results have no values
+ // (i.e. their times and counts are the only things of
+ // interest)... but perhaps it's the user's problem if they
+ // ask for segmentation (or any summary at all) in that case
+
+ for (int n = 0; n < int(source.results.size()); ++n) {
+
+ // This result spans source.results[n].time to
+ // source.results[n].time + source.results[n].duration.
+ // We need to dispose it into segments appropriately
+
+ RealTime resultStart = source.results[n].time;
+ RealTime resultEnd = resultStart + source.results[n].duration;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl;
+#endif
+
+ RealTime segmentStart = RealTime::zeroTime;
+ RealTime segmentEnd = resultEnd - RealTime(1, 0);
+
+ RealTime prevSegmentStart = segmentStart - RealTime(1, 0);
+
+ while (segmentEnd < resultEnd) {
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "segment end " << segmentEnd << " < result end "
+ << resultEnd << " (with result start " << resultStart << ")" << std::endl;
+#endif
+
+ findSegmentBounds(resultStart, segmentStart, segmentEnd);
+
+ if (segmentStart == prevSegmentStart) {
+ // This can happen when we reach the end of the
+ // input, if a feature's end time overruns the
+ // input audio end time
+ break;
+ }
+ prevSegmentStart = segmentStart;
+
+ RealTime chunkStart = resultStart;
+ if (chunkStart < segmentStart) chunkStart = segmentStart;
+
+ RealTime chunkEnd = resultEnd;
+ if (chunkEnd > segmentEnd) chunkEnd = segmentEnd;
+
+ m_segmentedAccumulators[output][segmentStart].bins = source.bins;
+
+ Result chunk;
+ chunk.time = chunkStart;
+ chunk.duration = chunkEnd - chunkStart;
+ chunk.values = source.results[n].values;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
+ std::cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << std::endl;
+#endif
+
+ m_segmentedAccumulators[output][segmentStart].results
+ .push_back(chunk);
+
+ resultStart = chunkEnd;
+ }
+ }
+ }
+}
+
+struct ValueDurationFloatPair
+{
+ float value;
+ float duration;
+
+ ValueDurationFloatPair() : value(0), duration(0) { }
+ ValueDurationFloatPair(float v, float d) : value(v), duration(d) { }
+ ValueDurationFloatPair &operator=(const ValueDurationFloatPair &p) {
+ value = p.value;
+ duration = p.duration;
+ return *this;
+ }
+ bool operator<(const ValueDurationFloatPair &p) const {
+ return value < p.value;
+ }
+};
+
+static double toSec(const RealTime &r)
+{
+ return r.sec + double(r.nsec) / 1000000000.0;
+}
+
+void
+PluginSummarisingAdapter::Impl::reduce()
+{
+ for (OutputSegmentAccumulatorMap::iterator i =
+ m_segmentedAccumulators.begin();
+ i != m_segmentedAccumulators.end(); ++i) {
+
+ int output = i->first;
+ SegmentAccumulatorMap &segments = i->second;
+
+ for (SegmentAccumulatorMap::iterator j = segments.begin();
+ j != segments.end(); ++j) {
+
+ RealTime segmentStart = j->first;
+ OutputAccumulator &accumulator = j->second;
+
+ int sz = accumulator.results.size();
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "reduce: segment starting at " << segmentStart
+ << " on output " << output << " has " << sz << " result(s)" << std::endl;
+#endif
+
+ double totalDuration = 0.0;
+ //!!! is this right?
+ if (sz > 0) {
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "last time = " << accumulator.results[sz-1].time
+ << ", duration = " << accumulator.results[sz-1].duration
+ << " (step = " << m_stepSize << ", block = " << m_blockSize << ")"
+ << std::endl;
+#endif
+ totalDuration = toSec((accumulator.results[sz-1].time +
+ accumulator.results[sz-1].duration) -
+ segmentStart);
+ }
+
+ for (int bin = 0; bin < accumulator.bins; ++bin) {
+
+ // work on all values over time for a single bin
+
+ OutputBinSummary summary;
+
+ summary.count = sz;
+
+ summary.minimum = 0.f;
+ summary.maximum = 0.f;
+
+ summary.median = 0.f;
+ summary.mode = 0.f;
+ summary.sum = 0.f;
+ summary.variance = 0.f;
+
+ summary.median_c = 0.f;
+ summary.mode_c = 0.f;
+ summary.mean_c = 0.f;
+ summary.variance_c = 0.f;
+
+ if (sz == 0) continue;
+
+ std::vector<ValueDurationFloatPair> valvec;
+
+ for (int k = 0; k < sz; ++k) {
+ while (int(accumulator.results[k].values.size()) <
+ accumulator.bins) {
+ accumulator.results[k].values.push_back(0.f);
+ }
+ }
+
+ for (int k = 0; k < sz; ++k) {
+ float value = accumulator.results[k].values[bin];
+ valvec.push_back(ValueDurationFloatPair
+ (value,
+ toSec(accumulator.results[k].duration)));
+ }
+
+ std::sort(valvec.begin(), valvec.end());
+
+ summary.minimum = valvec[0].value;
+ summary.maximum = valvec[sz-1].value;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "total duration = " << totalDuration << std::endl;
+#endif
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+/*
+ std::cerr << "value vector for medians:" << std::endl;
+ for (int k = 0; k < sz; ++k) {
+ std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") ";
+ }
+ std::cerr << std::endl;
+*/
+#endif
+
+ if (sz % 2 == 1) {
+ summary.median = valvec[sz/2].value;
+ } else {
+ summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2;
+ }
+
+ double duracc = 0.0;
+ summary.median_c = valvec[sz-1].value;
+
+ for (int k = 0; k < sz; ++k) {
+ duracc += valvec[k].duration;
+ if (duracc > totalDuration/2) {
+ summary.median_c = valvec[k].value;
+ break;
+ }
+ }
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "median_c = " << summary.median_c << std::endl;
+ std::cerr << "median = " << summary.median << std::endl;
+#endif
+
+ std::map<float, int> distribution;
+
+ for (int k = 0; k < sz; ++k) {
+ summary.sum += accumulator.results[k].values[bin];
+ distribution[accumulator.results[k].values[bin]] += 1;
+ }
+
+ int md = 0;
+
+ for (std::map<float, int>::iterator di = distribution.begin();
+ di != distribution.end(); ++di) {
+ if (di->second > md) {
+ md = di->second;
+ summary.mode = di->first;
+ }
+ }
+
+ distribution.clear();
+
+ std::map<float, double> distribution_c;
+
+ for (int k = 0; k < sz; ++k) {
+ distribution_c[accumulator.results[k].values[bin]]
+ += toSec(accumulator.results[k].duration);
+ }
+
+ double mrd = 0.0;
+
+ for (std::map<float, double>::iterator di = distribution_c.begin();
+ di != distribution_c.end(); ++di) {
+ if (di->second > mrd) {
+ mrd = di->second;
+ summary.mode_c = di->first;
+ }
+ }
+
+ distribution_c.clear();
+
+ if (totalDuration > 0.0) {
+
+ double sum_c = 0.0;
+
+ for (int k = 0; k < sz; ++k) {
+ double value = accumulator.results[k].values[bin]
+ * toSec(accumulator.results[k].duration);
+ sum_c += value;
+ }
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
+ << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl;
+#endif
+
+ summary.mean_c = sum_c / totalDuration;
+
+ for (int k = 0; k < sz; ++k) {
+ double value = accumulator.results[k].values[bin];
+// * toSec(accumulator.results[k].duration);
+ summary.variance_c +=
+ (value - summary.mean_c) * (value - summary.mean_c)
+ * toSec(accumulator.results[k].duration);
+ }
+
+// summary.variance_c /= summary.count;
+ summary.variance_c /= totalDuration;
+ }
+
+ double mean = summary.sum / summary.count;
+
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+ std::cerr << "mean = " << summary.sum << " / " << summary.count << " = "
+ << summary.sum / summary.count << std::endl;
+#endif
+
+ for (int k = 0; k < sz; ++k) {
+ float value = accumulator.results[k].values[bin];
+ summary.variance += (value - mean) * (value - mean);
+ }
+ summary.variance /= summary.count;
+
+ m_summaries[output][segmentStart][bin] = summary;
+ }
+ }
+ }
+
+ m_segmentedAccumulators.clear();
+ m_accumulators.clear();
+}
+
+
+}
+
+}
+
+_VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter.cpp)
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginWrapper.cpp
index dcbdf5b73a..02bdc280f1 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp
+++ b/libs/vamp-sdk/src/vamp-hostsdk/PluginWrapper.cpp
@@ -34,7 +34,9 @@
authorization.
*/
-#include "PluginWrapper.h"
+#include <vamp-hostsdk/PluginWrapper.h>
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginWrapper.cpp)
namespace Vamp {
@@ -199,3 +201,4 @@ PluginWrapper::getRemainingFeatures()
}
+_VAMP_SDK_HOSTSPACE_END(PluginWrapper.cpp)
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/RealTime.cpp b/libs/vamp-sdk/src/vamp-hostsdk/RealTime.cpp
new file mode 100644
index 0000000000..537ccbde5d
--- /dev/null
+++ b/libs/vamp-sdk/src/vamp-hostsdk/RealTime.cpp
@@ -0,0 +1,39 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include <vamp-hostsdk/RealTime.h>
+#include "../vamp-sdk/RealTime.cpp"
+
diff --git a/libs/vamp-sdk/src/vamp-sdk/PluginAdapter.cpp b/libs/vamp-sdk/src/vamp-sdk/PluginAdapter.cpp
new file mode 100644
index 0000000000..fc195d775b
--- /dev/null
+++ b/libs/vamp-sdk/src/vamp-sdk/PluginAdapter.cpp
@@ -0,0 +1,914 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include <vamp-sdk/PluginAdapter.h>
+
+#include <cstring>
+#include <cstdlib>
+
+#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
+#error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
+#endif
+
+
+//#define DEBUG_PLUGIN_ADAPTER 1
+
+_VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.cpp)
+
+namespace Vamp {
+
+class PluginAdapterBase::Impl
+{
+public:
+ Impl(PluginAdapterBase *);
+ ~Impl();
+
+ const VampPluginDescriptor *getDescriptor();
+
+protected:
+ PluginAdapterBase *m_base;
+
+ static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
+ float inputSampleRate);
+
+ static void vampCleanup(VampPluginHandle handle);
+
+ static int vampInitialise(VampPluginHandle handle, unsigned int channels,
+ unsigned int stepSize, unsigned int blockSize);
+
+ static void vampReset(VampPluginHandle handle);
+
+ static float vampGetParameter(VampPluginHandle handle, int param);
+ static void vampSetParameter(VampPluginHandle handle, int param, float value);
+
+ static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
+ static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
+
+ static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
+ static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
+ static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
+ static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
+
+ static unsigned int vampGetOutputCount(VampPluginHandle handle);
+
+ static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
+ unsigned int i);
+
+ static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
+
+ static VampFeatureList *vampProcess(VampPluginHandle handle,
+ const float *const *inputBuffers,
+ int sec,
+ int nsec);
+
+ static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
+
+ static void vampReleaseFeatureSet(VampFeatureList *fs);
+
+ void checkOutputMap(Plugin *plugin);
+ void markOutputsChanged(Plugin *plugin);
+
+ void cleanup(Plugin *plugin);
+ unsigned int getOutputCount(Plugin *plugin);
+ VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
+ unsigned int i);
+ VampFeatureList *process(Plugin *plugin,
+ const float *const *inputBuffers,
+ int sec, int nsec);
+ VampFeatureList *getRemainingFeatures(Plugin *plugin);
+ VampFeatureList *convertFeatures(Plugin *plugin,
+ const Plugin::FeatureSet &features);
+
+ // maps both plugins and descriptors to adapters
+ typedef std::map<const void *, Impl *> AdapterMap;
+ static AdapterMap *m_adapterMap;
+ static Impl *lookupAdapter(VampPluginHandle);
+
+ bool m_populated;
+ VampPluginDescriptor m_descriptor;
+ Plugin::ParameterList m_parameters;
+ Plugin::ProgramList m_programs;
+
+ typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
+ OutputMap m_pluginOutputs;
+
+ std::map<Plugin *, VampFeatureList *> m_fs;
+ std::map<Plugin *, std::vector<size_t> > m_fsizes;
+ std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
+ void resizeFS(Plugin *plugin, int n);
+ void resizeFL(Plugin *plugin, int n, size_t sz);
+ void resizeFV(Plugin *plugin, int n, int j, size_t sz);
+};
+
+PluginAdapterBase::PluginAdapterBase()
+{
+ m_impl = new Impl(this);
+}
+
+PluginAdapterBase::~PluginAdapterBase()
+{
+ delete m_impl;
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::getDescriptor()
+{
+ return m_impl->getDescriptor();
+}
+
+PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
+ m_base(base),
+ m_populated(false)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
+#endif
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::Impl::getDescriptor()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
+#endif
+
+ if (m_populated) return &m_descriptor;
+
+ Plugin *plugin = m_base->createPlugin(48000);
+
+ if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
+ std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
+ << "API version " << plugin->getVampApiVersion()
+ << " for\nplugin \"" << plugin->getIdentifier() << "\" "
+ << "differs from version "
+ << VAMP_API_VERSION << " for adapter.\n"
+ << "This plugin is probably linked against a different version of the Vamp SDK\n"
+ << "from the version it was compiled with. It will need to be re-linked correctly\n"
+ << "before it can be used." << std::endl;
+ delete plugin;
+ return 0;
+ }
+
+ m_parameters = plugin->getParameterDescriptors();
+ m_programs = plugin->getPrograms();
+
+ m_descriptor.vampApiVersion = plugin->getVampApiVersion();
+ m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
+ m_descriptor.name = strdup(plugin->getName().c_str());
+ m_descriptor.description = strdup(plugin->getDescription().c_str());
+ m_descriptor.maker = strdup(plugin->getMaker().c_str());
+ m_descriptor.pluginVersion = plugin->getPluginVersion();
+ m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
+
+ m_descriptor.parameterCount = m_parameters.size();
+ m_descriptor.parameters = (const VampParameterDescriptor **)
+ malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
+
+ unsigned int i;
+
+ for (i = 0; i < m_parameters.size(); ++i) {
+ VampParameterDescriptor *desc = (VampParameterDescriptor *)
+ malloc(sizeof(VampParameterDescriptor));
+ desc->identifier = strdup(m_parameters[i].identifier.c_str());
+ desc->name = strdup(m_parameters[i].name.c_str());
+ desc->description = strdup(m_parameters[i].description.c_str());
+ desc->unit = strdup(m_parameters[i].unit.c_str());
+ desc->minValue = m_parameters[i].minValue;
+ desc->maxValue = m_parameters[i].maxValue;
+ desc->defaultValue = m_parameters[i].defaultValue;
+ desc->isQuantized = m_parameters[i].isQuantized;
+ desc->quantizeStep = m_parameters[i].quantizeStep;
+ desc->valueNames = 0;
+ if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
+ desc->valueNames = (const char **)
+ malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
+ for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
+ desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
+ }
+ desc->valueNames[m_parameters[i].valueNames.size()] = 0;
+ }
+ m_descriptor.parameters[i] = desc;
+ }
+
+ m_descriptor.programCount = m_programs.size();
+ m_descriptor.programs = (const char **)
+ malloc(m_programs.size() * sizeof(const char *));
+
+ for (i = 0; i < m_programs.size(); ++i) {
+ m_descriptor.programs[i] = strdup(m_programs[i].c_str());
+ }
+
+ if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
+ m_descriptor.inputDomain = vampFrequencyDomain;
+ } else {
+ m_descriptor.inputDomain = vampTimeDomain;
+ }
+
+ m_descriptor.instantiate = vampInstantiate;
+ m_descriptor.cleanup = vampCleanup;
+ m_descriptor.initialise = vampInitialise;
+ m_descriptor.reset = vampReset;
+ m_descriptor.getParameter = vampGetParameter;
+ m_descriptor.setParameter = vampSetParameter;
+ m_descriptor.getCurrentProgram = vampGetCurrentProgram;
+ m_descriptor.selectProgram = vampSelectProgram;
+ m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
+ m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
+ m_descriptor.getMinChannelCount = vampGetMinChannelCount;
+ m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
+ m_descriptor.getOutputCount = vampGetOutputCount;
+ m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
+ m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
+ m_descriptor.process = vampProcess;
+ m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
+ m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
+
+ if (!m_adapterMap) {
+ m_adapterMap = new AdapterMap;
+ }
+ (*m_adapterMap)[&m_descriptor] = this;
+
+ delete plugin;
+
+ m_populated = true;
+ return &m_descriptor;
+}
+
+PluginAdapterBase::Impl::~Impl()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
+#endif
+
+ if (!m_populated) return;
+
+ free((void *)m_descriptor.identifier);
+ free((void *)m_descriptor.name);
+ free((void *)m_descriptor.description);
+ free((void *)m_descriptor.maker);
+ free((void *)m_descriptor.copyright);
+
+ for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
+ const VampParameterDescriptor *desc = m_descriptor.parameters[i];
+ free((void *)desc->identifier);
+ free((void *)desc->name);
+ free((void *)desc->description);
+ free((void *)desc->unit);
+ if (desc->valueNames) {
+ for (unsigned int j = 0; desc->valueNames[j]; ++j) {
+ free((void *)desc->valueNames[j]);
+ }
+ free((void *)desc->valueNames);
+ }
+ }
+ free((void *)m_descriptor.parameters);
+
+ for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
+ free((void *)m_descriptor.programs[i]);
+ }
+ free((void *)m_descriptor.programs);
+
+ if (m_adapterMap) {
+
+ m_adapterMap->erase(&m_descriptor);
+
+ if (m_adapterMap->empty()) {
+ delete m_adapterMap;
+ m_adapterMap = 0;
+ }
+ }
+}
+
+PluginAdapterBase::Impl *
+PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
+#endif
+
+ if (!m_adapterMap) return 0;
+ AdapterMap::const_iterator i = m_adapterMap->find(handle);
+ if (i == m_adapterMap->end()) return 0;
+ return i->second;
+}
+
+VampPluginHandle
+PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
+ float inputSampleRate)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
+#endif
+
+ if (!m_adapterMap) {
+ m_adapterMap = new AdapterMap();
+ }
+
+ if (m_adapterMap->find(desc) == m_adapterMap->end()) {
+ std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
+ return 0;
+ }
+
+ Impl *adapter = (*m_adapterMap)[desc];
+ if (desc != &adapter->m_descriptor) return 0;
+
+ Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
+ if (plugin) {
+ (*m_adapterMap)[plugin] = adapter;
+ }
+
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
+#endif
+
+ return plugin;
+}
+
+void
+PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) {
+ delete ((Plugin *)handle);
+ return;
+ }
+ adapter->cleanup(((Plugin *)handle));
+}
+
+int
+PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
+ unsigned int channels,
+ unsigned int stepSize,
+ unsigned int blockSize)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize);
+ adapter->markOutputsChanged((Plugin *)handle);
+ return result ? 1 : 0;
+}
+
+void
+PluginAdapterBase::Impl::vampReset(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
+#endif
+
+ ((Plugin *)handle)->reset();
+}
+
+float
+PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
+ int param)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0.0;
+ Plugin::ParameterList &list = adapter->m_parameters;
+ return ((Plugin *)handle)->getParameter(list[param].identifier);
+}
+
+void
+PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
+ int param, float value)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return;
+ Plugin::ParameterList &list = adapter->m_parameters;
+ ((Plugin *)handle)->setParameter(list[param].identifier, value);
+ adapter->markOutputsChanged((Plugin *)handle);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ Plugin::ProgramList &list = adapter->m_programs;
+ std::string program = ((Plugin *)handle)->getCurrentProgram();
+ for (unsigned int i = 0; i < list.size(); ++i) {
+ if (list[i] == program) return i;
+ }
+ return 0;
+}
+
+void
+PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
+ unsigned int program)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return;
+
+ Plugin::ProgramList &list = adapter->m_programs;
+ ((Plugin *)handle)->selectProgram(list[program]);
+
+ adapter->markOutputsChanged((Plugin *)handle);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getPreferredStepSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getPreferredBlockSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getMinChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getMaxChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+
+// std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+ if (!adapter) return 0;
+ return adapter->getOutputCount((Plugin *)handle);
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
+ unsigned int i)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+
+// std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+ if (!adapter) return 0;
+ return adapter->getOutputDescriptor((Plugin *)handle, i);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
+#endif
+
+ if (desc->identifier) free((void *)desc->identifier);
+ if (desc->name) free((void *)desc->name);
+ if (desc->description) free((void *)desc->description);
+ if (desc->unit) free((void *)desc->unit);
+ if (desc->hasFixedBinCount && desc->binNames) {
+ for (unsigned int i = 0; i < desc->binCount; ++i) {
+ if (desc->binNames[i]) {
+ free((void *)desc->binNames[i]);
+ }
+ }
+ }
+ if (desc->binNames) free((void *)desc->binNames);
+ free((void *)desc);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
+ const float *const *inputBuffers,
+ int sec,
+ int nsec)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ return adapter->process((Plugin *)handle, inputBuffers, sec, nsec);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ return adapter->getRemainingFeatures((Plugin *)handle);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
+#endif
+}
+
+void
+PluginAdapterBase::Impl::cleanup(Plugin *plugin)
+{
+ if (m_fs.find(plugin) != m_fs.end()) {
+ size_t outputCount = 0;
+ if (m_pluginOutputs[plugin]) {
+ outputCount = m_pluginOutputs[plugin]->size();
+ }
+ VampFeatureList *list = m_fs[plugin];
+ for (unsigned int i = 0; i < outputCount; ++i) {
+ for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
+ if (list[i].features[j].v1.label) {
+ free(list[i].features[j].v1.label);
+ }
+ if (list[i].features[j].v1.values) {
+ free(list[i].features[j].v1.values);
+ }
+ }
+ if (list[i].features) free(list[i].features);
+ }
+ m_fs.erase(plugin);
+ m_fsizes.erase(plugin);
+ m_fvsizes.erase(plugin);
+ }
+
+ if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
+ delete m_pluginOutputs[plugin];
+ m_pluginOutputs.erase(plugin);
+ }
+
+ if (m_adapterMap) {
+ m_adapterMap->erase(plugin);
+
+ if (m_adapterMap->empty()) {
+ delete m_adapterMap;
+ m_adapterMap = 0;
+ }
+ }
+
+ delete ((Plugin *)plugin);
+}
+
+void
+PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
+{
+ OutputMap::iterator i = m_pluginOutputs.find(plugin);
+
+ if (i == m_pluginOutputs.end() || !i->second) {
+
+ m_pluginOutputs[plugin] = new Plugin::OutputList
+ (plugin->getOutputDescriptors());
+
+// std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
+ }
+}
+
+void
+PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin)
+{
+ OutputMap::iterator i = m_pluginOutputs.find(plugin);
+
+// std::cerr << "PluginAdapterBase::Impl::markOutputsChanged" << std::endl;
+
+ if (i != m_pluginOutputs.end()) {
+
+ Plugin::OutputList *list = i->second;
+ m_pluginOutputs.erase(i);
+ delete list;
+ }
+}
+
+unsigned int
+PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
+{
+ checkOutputMap(plugin);
+
+ return m_pluginOutputs[plugin]->size();
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
+ unsigned int i)
+{
+ checkOutputMap(plugin);
+
+ Plugin::OutputDescriptor &od =
+ (*m_pluginOutputs[plugin])[i];
+
+ VampOutputDescriptor *desc = (VampOutputDescriptor *)
+ malloc(sizeof(VampOutputDescriptor));
+
+ desc->identifier = strdup(od.identifier.c_str());
+ desc->name = strdup(od.name.c_str());
+ desc->description = strdup(od.description.c_str());
+ desc->unit = strdup(od.unit.c_str());
+ desc->hasFixedBinCount = od.hasFixedBinCount;
+ desc->binCount = od.binCount;
+
+ if (od.hasFixedBinCount && od.binCount > 0
+ // We would like to do "&& !od.binNames.empty()" here -- but we
+ // can't, because it will crash older versions of the host adapter
+ // which try to copy the names across whenever the bin count is
+ // non-zero, regardless of whether they exist or not
+ ) {
+ desc->binNames = (const char **)
+ malloc(od.binCount * sizeof(const char *));
+
+ for (unsigned int i = 0; i < od.binCount; ++i) {
+ if (i < od.binNames.size()) {
+ desc->binNames[i] = strdup(od.binNames[i].c_str());
+ } else {
+ desc->binNames[i] = 0;
+ }
+ }
+ } else {
+ desc->binNames = 0;
+ }
+
+ desc->hasKnownExtents = od.hasKnownExtents;
+ desc->minValue = od.minValue;
+ desc->maxValue = od.maxValue;
+ desc->isQuantized = od.isQuantized;
+ desc->quantizeStep = od.quantizeStep;
+
+ switch (od.sampleType) {
+ case Plugin::OutputDescriptor::OneSamplePerStep:
+ desc->sampleType = vampOneSamplePerStep; break;
+ case Plugin::OutputDescriptor::FixedSampleRate:
+ desc->sampleType = vampFixedSampleRate; break;
+ case Plugin::OutputDescriptor::VariableSampleRate:
+ desc->sampleType = vampVariableSampleRate; break;
+ }
+
+ desc->sampleRate = od.sampleRate;
+ desc->hasDuration = od.hasDuration;
+
+ return desc;
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::process(Plugin *plugin,
+ const float *const *inputBuffers,
+ int sec, int nsec)
+{
+// std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
+ RealTime rt(sec, nsec);
+ checkOutputMap(plugin);
+ return convertFeatures(plugin, plugin->process(inputBuffers, rt));
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
+{
+// std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
+ checkOutputMap(plugin);
+ return convertFeatures(plugin, plugin->getRemainingFeatures());
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
+ const Plugin::FeatureSet &features)
+{
+ int lastN = -1;
+
+ int outputCount = 0;
+ if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
+
+ resizeFS(plugin, outputCount);
+ VampFeatureList *fs = m_fs[plugin];
+
+// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << std::endl;
+
+ for (Plugin::FeatureSet::const_iterator fi = features.begin();
+ fi != features.end(); ++fi) {
+
+ int n = fi->first;
+
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
+
+ if (n >= int(outputCount)) {
+ std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
+ continue;
+ }
+
+ if (n > lastN + 1) {
+ for (int i = lastN + 1; i < n; ++i) {
+ fs[i].featureCount = 0;
+ }
+ }
+
+ const Plugin::FeatureList &fl = fi->second;
+
+ size_t sz = fl.size();
+ if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
+ fs[n].featureCount = sz;
+
+ for (size_t j = 0; j < sz; ++j) {
+
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
+
+ VampFeature *feature = &fs[n].features[j].v1;
+
+ feature->hasTimestamp = fl[j].hasTimestamp;
+ feature->sec = fl[j].timestamp.sec;
+ feature->nsec = fl[j].timestamp.nsec;
+ feature->valueCount = fl[j].values.size();
+
+ VampFeatureV2 *v2 = &fs[n].features[j + sz].v2;
+
+ v2->hasDuration = fl[j].hasDuration;
+ v2->durationSec = fl[j].duration.sec;
+ v2->durationNsec = fl[j].duration.nsec;
+
+ if (feature->label) free(feature->label);
+
+ if (fl[j].label.empty()) {
+ feature->label = 0;
+ } else {
+ feature->label = strdup(fl[j].label.c_str());
+ }
+
+ if (feature->valueCount > m_fvsizes[plugin][n][j]) {
+ resizeFV(plugin, n, j, feature->valueCount);
+ }
+
+ for (unsigned int k = 0; k < feature->valueCount; ++k) {
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
+ feature->values[k] = fl[j].values[k];
+ }
+ }
+
+ lastN = n;
+ }
+
+ if (lastN == -1) return 0;
+
+ if (int(outputCount) > lastN + 1) {
+ for (int i = lastN + 1; i < int(outputCount); ++i) {
+ fs[i].featureCount = 0;
+ }
+ }
+
+// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << std::endl;
+// for (int i = 0; i < outputCount; ++i) {
+// std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << std::endl;
+// }
+
+
+ return fs;
+}
+
+void
+PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
+
+ int i = m_fsizes[plugin].size();
+ if (i >= n) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin] = (VampFeatureList *)realloc
+ (m_fs[plugin], n * sizeof(VampFeatureList));
+
+ while (i < n) {
+ m_fs[plugin][i].featureCount = 0;
+ m_fs[plugin][i].features = 0;
+ m_fsizes[plugin].push_back(0);
+ m_fvsizes[plugin].push_back(std::vector<size_t>());
+ i++;
+ }
+}
+
+void
+PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
+// << sz << ")" << std::endl;
+
+ size_t i = m_fsizes[plugin][n];
+ if (i >= sz) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin][n].features = (VampFeatureUnion *)realloc
+ (m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion));
+
+ while (m_fsizes[plugin][n] < sz) {
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0;
+ m_fvsizes[plugin][n].push_back(0);
+ m_fsizes[plugin][n]++;
+ }
+}
+
+void
+PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
+// << j << ", " << sz << ")" << std::endl;
+
+ size_t i = m_fvsizes[plugin][n][j];
+ if (i >= sz) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin][n].features[j].v1.values = (float *)realloc
+ (m_fs[plugin][n].features[j].v1.values, sz * sizeof(float));
+
+ m_fvsizes[plugin][n][j] = sz;
+}
+
+PluginAdapterBase::Impl::AdapterMap *
+PluginAdapterBase::Impl::m_adapterMap = 0;
+
+}
+
+_VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp)
+
diff --git a/libs/vamp-sdk/src/vamp-sdk/RealTime.cpp b/libs/vamp-sdk/src/vamp-sdk/RealTime.cpp
new file mode 100644
index 0000000000..d3c4364785
--- /dev/null
+++ b/libs/vamp-sdk/src/vamp-sdk/RealTime.cpp
@@ -0,0 +1,252 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+/*
+ This is a modified version of a source file from the
+ Rosegarden MIDI and audio sequencer and notation editor.
+ This file copyright 2000-2006 Chris Cannam.
+ Relicensed by the author as detailed above.
+*/
+
+#include <iostream>
+
+#if (__GNUC__ < 3)
+#include <strstream>
+#define stringstream strstream
+#else
+#include <sstream>
+#endif
+
+using std::cerr;
+using std::endl;
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+#include <vamp-sdk/RealTime.h>
+
+_VAMP_SDK_PLUGSPACE_BEGIN(RealTime.cpp)
+
+namespace Vamp {
+
+// A RealTime consists of two ints that must be at least 32 bits each.
+// A signed 32-bit int can store values exceeding +/- 2 billion. This
+// means we can safely use our lower int for nanoseconds, as there are
+// 1 billion nanoseconds in a second and we need to handle double that
+// because of the implementations of addition etc that we use.
+//
+// The maximum valid RealTime on a 32-bit system is somewhere around
+// 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
+
+#define ONE_BILLION 1000000000
+
+RealTime::RealTime(int s, int n) :
+ sec(s), nsec(n)
+{
+ if (sec == 0) {
+ while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+ while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+ } else if (sec < 0) {
+ while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+ while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
+ } else {
+ while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+ while (nsec < 0) { nsec += ONE_BILLION; --sec; }
+ }
+}
+
+RealTime
+RealTime::fromSeconds(double sec)
+{
+ return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
+}
+
+RealTime
+RealTime::fromMilliseconds(int msec)
+{
+ return RealTime(msec / 1000, (msec % 1000) * 1000000);
+}
+
+#ifndef _WIN32
+RealTime
+RealTime::fromTimeval(const struct timeval &tv)
+{
+ return RealTime(tv.tv_sec, tv.tv_usec * 1000);
+}
+#endif
+
+std::ostream &operator<<(std::ostream &out, const RealTime &rt)
+{
+ if (rt < RealTime::zeroTime) {
+ out << "-";
+ } else {
+ out << " ";
+ }
+
+ int s = (rt.sec < 0 ? -rt.sec : rt.sec);
+ int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
+
+ out << s << ".";
+
+ int nn(n);
+ if (nn == 0) out << "00000000";
+ else while (nn < (ONE_BILLION / 10)) {
+ out << "0";
+ nn *= 10;
+ }
+
+ out << n << "R";
+ return out;
+}
+
+std::string
+RealTime::toString() const
+{
+ std::stringstream out;
+ out << *this;
+
+#if (__GNUC__ < 3)
+ out << std::ends;
+#endif
+
+ std::string s = out.str();
+
+ // remove trailing R
+ return s.substr(0, s.length() - 1);
+}
+
+std::string
+RealTime::toText(bool fixedDp) const
+{
+ if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
+
+ std::stringstream out;
+
+ if (sec >= 3600) {
+ out << (sec / 3600) << ":";
+ }
+
+ if (sec >= 60) {
+ out << (sec % 3600) / 60 << ":";
+ }
+
+ if (sec >= 10) {
+ out << ((sec % 60) / 10);
+ }
+
+ out << (sec % 10);
+
+ int ms = msec();
+
+ if (ms != 0) {
+ out << ".";
+ out << (ms / 100);
+ ms = ms % 100;
+ if (ms != 0) {
+ out << (ms / 10);
+ ms = ms % 10;
+ } else if (fixedDp) {
+ out << "0";
+ }
+ if (ms != 0) {
+ out << ms;
+ } else if (fixedDp) {
+ out << "0";
+ }
+ } else if (fixedDp) {
+ out << ".000";
+ }
+
+#if (__GNUC__ < 3)
+ out << std::ends;
+#endif
+
+ std::string s = out.str();
+
+ return s;
+}
+
+
+RealTime
+RealTime::operator/(int d) const
+{
+ int secdiv = sec / d;
+ int secrem = sec % d;
+
+ double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
+
+ return RealTime(secdiv, int(nsecdiv + 0.5));
+}
+
+double
+RealTime::operator/(const RealTime &r) const
+{
+ double lTotal = double(sec) * ONE_BILLION + double(nsec);
+ double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
+
+ if (rTotal == 0) return 0.0;
+ else return lTotal/rTotal;
+}
+
+long
+RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
+{
+ if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
+ double s = time.sec + double(time.nsec + 1) / 1000000000.0;
+ return long(s * sampleRate);
+}
+
+RealTime
+RealTime::frame2RealTime(long frame, unsigned int sampleRate)
+{
+ if (frame < 0) return -frame2RealTime(-frame, sampleRate);
+
+ RealTime rt;
+ rt.sec = frame / long(sampleRate);
+ frame -= rt.sec * long(sampleRate);
+ rt.nsec = (int)(((double(frame) * 1000000.0) / sampleRate) * 1000.0);
+ return rt;
+}
+
+const RealTime RealTime::zeroTime(0,0);
+
+}
+
+_VAMP_SDK_PLUGSPACE_END(RealTime.cpp)
+
+
+
diff --git a/libs/vamp-sdk/vamp-hostsdk/Plugin.h b/libs/vamp-sdk/vamp-hostsdk/Plugin.h
new file mode 100644
index 0000000000..72a3b640d5
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/Plugin.h
@@ -0,0 +1,47 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_HOSTSDK_PLUGIN_H_
+#define _VAMP_HOSTSDK_PLUGIN_H_
+
+// Do not include vamp-sdk/Plugin.h directly from host code. Always
+// use this header instead.
+
+#include "hostguard.h"
+
+#include <vamp-sdk/Plugin.h>
+
+#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/PluginBase.h b/libs/vamp-sdk/vamp-hostsdk/PluginBase.h
new file mode 100644
index 0000000000..f12c25a715
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginBase.h
@@ -0,0 +1,47 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_HOSTSDK_PLUGIN_BASE_H_
+#define _VAMP_HOSTSDK_PLUGIN_BASE_H_
+
+// Do not include vamp-sdk/PluginBase.h directly from host code.
+// Always use this header instead.
+
+#include "hostguard.h"
+
+#include <vamp-sdk/PluginBase.h>
+
+#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/PluginBufferingAdapter.h b/libs/vamp-sdk/vamp-hostsdk/PluginBufferingAdapter.h
new file mode 100644
index 0000000000..21c2b36d74
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginBufferingAdapter.h
@@ -0,0 +1,194 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+ This file by Mark Levy and Chris Cannam, Copyright 2007-2008 QMUL.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_BUFFERING_ADAPTER_H_
+#define _VAMP_PLUGIN_BUFFERING_ADAPTER_H_
+
+#include "hostguard.h"
+#include "PluginWrapper.h"
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginBufferingAdapter.h)
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginBufferingAdapter PluginBufferingAdapter.h <vamp-hostsdk/PluginBufferingAdapter.h>
+ *
+ * PluginBufferingAdapter is a Vamp plugin adapter that allows plugins
+ * to be used by a host supplying an audio stream in non-overlapping
+ * buffers of arbitrary size.
+ *
+ * A host using PluginBufferingAdapter may ignore the preferred step
+ * and block size reported by the plugin, and still expect the plugin
+ * to run. The value of blockSize and stepSize passed to initialise
+ * should be the size of the buffer which the host will supply; the
+ * stepSize should be equal to the blockSize.
+ *
+ * If the internal step size used for the plugin differs from that
+ * supplied by the host, the adapter will modify the sample type and
+ * rate specifications for the plugin outputs appropriately, and set
+ * timestamps on the output features for outputs that formerly used a
+ * different sample rate specification. This is necessary in order to
+ * obtain correct time stamping.
+ *
+ * In other respects, the PluginBufferingAdapter behaves identically
+ * to the plugin that it wraps. The wrapped plugin will be deleted
+ * when the wrapper is deleted.
+ */
+
+class PluginBufferingAdapter : public PluginWrapper
+{
+public:
+ /**
+ * Construct a PluginBufferingAdapter wrapping the given plugin.
+ * The adapter takes ownership of the plugin, which will be
+ * deleted when the adapter is deleted.
+ */
+ PluginBufferingAdapter(Plugin *plugin);
+ virtual ~PluginBufferingAdapter();
+
+ /**
+ * Return the preferred step size for this adapter.
+ *
+ * Because of the way this adapter works, its preferred step size
+ * will always be the same as its preferred block size. This may
+ * or may not be the same as the preferred step size of the
+ * underlying plugin, which may be obtained by calling
+ * getPluginPreferredStepSize().
+ */
+ size_t getPreferredStepSize() const;
+
+ /**
+ * Return the preferred block size for this adapter.
+ *
+ * This may or may not be the same as the preferred block size of
+ * the underlying plugin, which may be obtained by calling
+ * getPluginPreferredBlockSize().
+ *
+ * Note that this adapter may be initialised with any block size,
+ * not just its supposedly preferred one.
+ */
+ size_t getPreferredBlockSize() const;
+
+ /**
+ * Initialise the adapter (and therefore the plugin) for the given
+ * number of channels. Initialise the adapter for the given step
+ * and block size, which must be equal.
+ *
+ * The step and block size used for the underlying plugin will
+ * depend on its preferences, or any values previously passed to
+ * setPluginStepSize and setPluginBlockSize.
+ */
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ /**
+ * Return the preferred step size of the plugin wrapped by this
+ * adapter.
+ *
+ * This is included mainly for informational purposes. This value
+ * is not likely to be a valid step size for the adapter itself,
+ * and it is not usually of any use in interpreting the results
+ * (because the adapter re-writes OneSamplePerStep outputs to
+ * FixedSampleRate so that the hop size no longer needs to be
+ * known beforehand in order to interpret them).
+ */
+ size_t getPluginPreferredStepSize() const;
+
+ /**
+ * Return the preferred block size of the plugin wrapped by this
+ * adapter.
+ *
+ * This is included mainly for informational purposes.
+ */
+ size_t getPluginPreferredBlockSize() const;
+
+ /**
+ * Set the step size that will be used for the underlying plugin
+ * when initialise() is called. If this is not set, the plugin's
+ * own preferred step size will be used. You will not usually
+ * need to call this function. If you do call it, it must be
+ * before the first call to initialise().
+ */
+ void setPluginStepSize(size_t stepSize);
+
+ /**
+ * Set the block size that will be used for the underlying plugin
+ * when initialise() is called. If this is not set, the plugin's
+ * own preferred block size will be used. You will not usually
+ * need to call this function. If you do call it, it must be
+ * before the first call to initialise().
+ */
+ void setPluginBlockSize(size_t blockSize);
+
+ /**
+ * Return the step and block sizes that were actually used when
+ * initialising the underlying plugin.
+ *
+ * This is included mainly for informational purposes. You will
+ * not usually need to call this function. If this is called
+ * before initialise(), it will return 0 for both values. If it
+ * is called after a failed call to initialise(), it will return
+ * the values that were used in the failed call to the plugin's
+ * initialise() function.
+ */
+ void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize);
+
+ void setParameter(std::string, float);
+ void selectProgram(std::string);
+
+ OutputList getOutputDescriptors() const;
+
+ void reset();
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+ FeatureSet getRemainingFeatures();
+
+protected:
+ class Impl;
+ Impl *m_impl;
+};
+
+}
+
+}
+
+_VAMP_SDK_HOSTSPACE_END(PluginBufferingAdapter.h)
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h b/libs/vamp-sdk/vamp-hostsdk/PluginChannelAdapter.h
index a2b4d89aee..28ee82ae7d 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginChannelAdapter.h
@@ -37,14 +37,17 @@
#ifndef _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
#define _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
+#include "hostguard.h"
#include "PluginWrapper.h"
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginChannelAdapter.h)
+
namespace Vamp {
namespace HostExt {
/**
- * \class PluginChannelAdapter PluginChannelAdapter.h <vamp-sdk/hostext/PluginChannelAdapter.h>
+ * \class PluginChannelAdapter PluginChannelAdapter.h <vamp-hostsdk/PluginChannelAdapter.h>
*
* PluginChannelAdapter is a Vamp plugin adapter that implements a
* policy for management of plugins that expect a different number of
@@ -109,13 +112,29 @@ namespace HostExt {
class PluginChannelAdapter : public PluginWrapper
{
public:
- PluginChannelAdapter(Plugin *plugin); // I take ownership of plugin
+ /**
+ * Construct a PluginChannelAdapter wrapping the given plugin.
+ * The adapter takes ownership of the plugin, which will be
+ * deleted when the adapter is deleted.
+ */
+ PluginChannelAdapter(Plugin *plugin);
virtual ~PluginChannelAdapter();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+ /**
+ * Call process(), providing interleaved audio data with the
+ * number of channels passed to initialise(). The adapter will
+ * de-interleave into temporary buffers as appropriate before
+ * calling process().
+ *
+ * \note This function was introduced in version 1.4 of the Vamp
+ * plugin SDK.
+ */
+ FeatureSet processInterleaved(const float *inputBuffer, RealTime timestamp);
+
protected:
class Impl;
Impl *m_impl;
@@ -125,4 +144,6 @@ protected:
}
+_VAMP_SDK_HOSTSPACE_END(PluginChannelAdapter.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/PluginHostAdapter.h b/libs/vamp-sdk/vamp-hostsdk/PluginHostAdapter.h
new file mode 100644
index 0000000000..2ca1d69949
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginHostAdapter.h
@@ -0,0 +1,123 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_HOST_ADAPTER_H_
+#define _VAMP_PLUGIN_HOST_ADAPTER_H_
+
+#include "hostguard.h"
+#include "Plugin.h"
+
+#include <vamp/vamp.h>
+
+#include <vector>
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.h)
+
+namespace Vamp {
+
+/**
+ * \class PluginHostAdapter PluginHostAdapter.h <vamp-hostsdk/PluginHostAdapter.h>
+ *
+ * PluginHostAdapter is a wrapper class that a Vamp host can use to
+ * make the C-language VampPluginDescriptor object appear as a C++
+ * Vamp::Plugin object.
+ *
+ * The Vamp API is defined in vamp/vamp.h as a C API. The C++ objects
+ * used for convenience by plugins and hosts actually communicate
+ * using the C low-level API, but the details of this communication
+ * are handled seamlessly by the Vamp SDK implementation provided the
+ * plugin and host use the proper C++ wrapper objects.
+ *
+ * See also PluginAdapter, the plugin-side wrapper that makes a C++
+ * plugin object available using the C query API.
+ */
+
+class PluginHostAdapter : public Plugin
+{
+public:
+ PluginHostAdapter(const VampPluginDescriptor *descriptor,
+ float inputSampleRate);
+ virtual ~PluginHostAdapter();
+
+ static std::vector<std::string> getPluginPath();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+ void reset();
+
+ InputDomain getInputDomain() const;
+
+ unsigned int getVampApiVersion() const;
+ 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);
+
+ ProgramList getPrograms() const;
+ std::string getCurrentProgram() const;
+ void selectProgram(std::string);
+
+ size_t getPreferredStepSize() const;
+ size_t getPreferredBlockSize() const;
+
+ size_t getMinChannelCount() const;
+ size_t getMaxChannelCount() const;
+
+ OutputList getOutputDescriptors() const;
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+ FeatureSet getRemainingFeatures();
+
+protected:
+ void convertFeatures(VampFeatureList *, FeatureSet &);
+
+ const VampPluginDescriptor *m_descriptor;
+ VampPluginHandle m_handle;
+};
+
+}
+
+_VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.h)
+
+#endif
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h b/libs/vamp-sdk/vamp-hostsdk/PluginInputDomainAdapter.h
index 73da053149..7f7c11c3be 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginInputDomainAdapter.h
@@ -37,14 +37,17 @@
#ifndef _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
#define _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
+#include "hostguard.h"
#include "PluginWrapper.h"
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.h)
+
namespace Vamp {
namespace HostExt {
/**
- * \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-sdk/hostext/PluginInputDomainAdapter.h>
+ * \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-hostsdk/PluginInputDomainAdapter.h>
*
* PluginInputDomainAdapter is a Vamp plugin adapter that converts
* time-domain input into frequency-domain input for plugins that need
@@ -79,7 +82,12 @@ namespace HostExt {
class PluginInputDomainAdapter : public PluginWrapper
{
public:
- PluginInputDomainAdapter(Plugin *plugin); // I take ownership of plugin
+ /**
+ * Construct a PluginInputDomainAdapter wrapping the given plugin.
+ * The adapter takes ownership of the plugin, which will be
+ * deleted when the adapter is deleted.
+ */
+ PluginInputDomainAdapter(Plugin *plugin);
virtual ~PluginInputDomainAdapter();
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
@@ -91,6 +99,29 @@ public:
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+ /**
+ * Return the amount by which the timestamps supplied to process()
+ * are being incremented when they are passed to the plugin's own
+ * process() implementation.
+ *
+ * The Vamp API mandates that the timestamp passed to the plugin
+ * for time-domain input should be the time of the first sample in
+ * the block, but the timestamp passed for frequency-domain input
+ * should be the timestamp of the centre of the block.
+ *
+ * The PluginInputDomainAdapter adjusts its timestamps properly so
+ * that the plugin receives correct times, but in some
+ * circumstances (such as for establishing the correct timing of
+ * implicitly-timed features, i.e. features without their own
+ * timestamps) the host may need to be aware that this adjustment
+ * is taking place.
+ *
+ * If the plugin requires time-domain input, this function will
+ * return zero. The result of calling this function before
+ * initialise() has been called is undefined.
+ */
+ RealTime getTimestampAdjustment() const;
+
protected:
class Impl;
Impl *m_impl;
@@ -100,4 +131,6 @@ protected:
}
+_VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h b/libs/vamp-sdk/vamp-hostsdk/PluginLoader.h
index f48143c11e..4d1daffd25 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginLoader.h
@@ -41,8 +41,11 @@
#include <string>
#include <map>
+#include "hostguard.h"
#include "PluginWrapper.h"
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.h)
+
namespace Vamp {
class Plugin;
@@ -50,7 +53,7 @@ class Plugin;
namespace HostExt {
/**
- * \class PluginLoader PluginLoader.h <vamp-sdk/hostext/PluginLoader.h>
+ * \class PluginLoader PluginLoader.h <vamp-hostsdk/PluginLoader.h>
*
* Vamp::HostExt::PluginLoader is a convenience class for discovering
* and loading Vamp plugins using the typical plugin-path, library
@@ -234,5 +237,7 @@ protected:
}
+_VAMP_SDK_HOSTSPACE_END(PluginLoader.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/PluginSummarisingAdapter.h b/libs/vamp-sdk/vamp-hostsdk/PluginSummarisingAdapter.h
new file mode 100644
index 0000000000..e9c14f5d2b
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginSummarisingAdapter.h
@@ -0,0 +1,197 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2008 Chris Cannam and QMUL.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_SUMMARISING_ADAPTER_H_
+#define _VAMP_PLUGIN_SUMMARISING_ADAPTER_H_
+
+#include "hostguard.h"
+#include "PluginWrapper.h"
+
+#include <set>
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter.h)
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginSummarisingAdapter PluginSummarisingAdapter.h <vamp-hostsdk/PluginSummarisingAdapter.h>
+ *
+ * PluginSummarisingAdapter is a Vamp plugin adapter that provides
+ * summarisation methods such as mean and median averages of output
+ * features, for use in any context where an available plugin produces
+ * individual values but the result that is actually needed is some
+ * sort of aggregate.
+ *
+ * To make use of PluginSummarisingAdapter, the host should configure,
+ * initialise and run the plugin through the adapter interface just as
+ * normal. Then, after the process and getRemainingFeatures methods
+ * have been properly called and processing is complete, the host may
+ * call getSummaryForOutput or getSummaryForAllOutputs to obtain
+ * summarised features: averages, maximum values, etc, depending on
+ * the SummaryType passed to the function.
+ *
+ * By default PluginSummarisingAdapter calculates a single summary of
+ * each output's feature across the whole duration of processed audio.
+ * A host needing summaries of sub-segments of the whole audio may
+ * call setSummarySegmentBoundaries before retrieving the summaries,
+ * providing a list of times such that one summary will be provided
+ * for each segment between two consecutive times.
+ *
+ * PluginSummarisingAdapter is straightforward rather than fast. It
+ * calculates all of the summary types for all outputs always, and
+ * then returns only the ones that are requested. It is designed on
+ * the basis that, for most features, summarising and storing
+ * summarised results is far cheaper than calculating the results in
+ * the first place. If this is not true for your particular feature,
+ * PluginSummarisingAdapter may not be the best approach for you.
+ *
+ * \note This class was introduced in version 2.0 of the Vamp plugin SDK.
+ */
+
+class PluginSummarisingAdapter : public PluginWrapper
+{
+public:
+ /**
+ * Construct a PluginSummarisingAdapter wrapping the given plugin.
+ * The adapter takes ownership of the plugin, which will be
+ * deleted when the adapter is deleted.
+ */
+ PluginSummarisingAdapter(Plugin *plugin);
+ virtual ~PluginSummarisingAdapter();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ void reset();
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+ FeatureSet getRemainingFeatures();
+
+ typedef std::set<RealTime> SegmentBoundaries;
+
+ /**
+ * Specify a series of segment boundaries, such that one summary
+ * will be returned for each of the contiguous intra-boundary
+ * segments. This function must be called before
+ * getSummaryForOutput or getSummaryForAllOutputs.
+ *
+ * Note that you cannot retrieve results with multiple different
+ * segmentations by repeatedly calling this function followed by
+ * one of the getSummary functions. The summaries are all
+ * calculated at the first call to any getSummary function, and
+ * once the summaries have been calculated, they remain
+ * calculated.
+ */
+ void setSummarySegmentBoundaries(const SegmentBoundaries &);
+
+ enum SummaryType {
+ Minimum = 0,
+ Maximum = 1,
+ Mean = 2,
+ Median = 3,
+ Mode = 4,
+ Sum = 5,
+ Variance = 6,
+ StandardDeviation = 7,
+ Count = 8,
+
+ UnknownSummaryType = 999
+ };
+
+ /**
+ * AveragingMethod indicates how the adapter should handle
+ * average-based summaries of features whose results are not
+ * equally spaced in time.
+ *
+ * If SampleAverage is specified, summary types based on averages
+ * will be calculated by treating each result individually without
+ * regard to its time: for example, the mean will be the sum of
+ * all values divided by the number of values.
+ *
+ * If ContinuousTimeAverage is specified, each feature will be
+ * considered to have a duration, either as specified in the
+ * feature's duration field, or until the following feature: thus,
+ * for example, the mean will be the sum of the products of values
+ * and durations, divided by the total duration.
+ *
+ * Although SampleAverage is useful for many types of feature,
+ * ContinuousTimeAverage is essential for some situations, for
+ * example finding the result that spans the largest proportion of
+ * the input given a feature that emits a new result only when the
+ * value changes (the modal value integrated over time).
+ */
+ enum AveragingMethod {
+ SampleAverage = 0,
+ ContinuousTimeAverage = 1,
+ };
+
+ /**
+ * Return summaries of the features that were returned on the
+ * given output, using the given SummaryType and AveragingMethod.
+ *
+ * The plugin must have been fully run (process() and
+ * getRemainingFeatures() calls all made as appropriate) before
+ * this function is called.
+ */
+ FeatureList getSummaryForOutput(int output,
+ SummaryType type,
+ AveragingMethod method = SampleAverage);
+
+ /**
+ * Return summaries of the features that were returned on all of
+ * the plugin's outputs, using the given SummaryType and
+ * AveragingMethod.
+ *
+ * The plugin must have been fully run (process() and
+ * getRemainingFeatures() calls all made as appropriate) before
+ * this function is called.
+ */
+ FeatureSet getSummaryForAllOutputs(SummaryType type,
+ AveragingMethod method = SampleAverage);
+
+protected:
+ class Impl;
+ Impl *m_impl;
+};
+
+}
+
+}
+
+_VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter.h)
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h b/libs/vamp-sdk/vamp-hostsdk/PluginWrapper.h
index d5ec1da0e8..357050d2be 100644
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h
+++ b/libs/vamp-sdk/vamp-hostsdk/PluginWrapper.h
@@ -37,14 +37,17 @@
#ifndef _VAMP_PLUGIN_WRAPPER_H_
#define _VAMP_PLUGIN_WRAPPER_H_
-#include <vamp-sdk/Plugin.h>
+#include "hostguard.h"
+#include <vamp-hostsdk/Plugin.h>
+
+_VAMP_SDK_HOSTSPACE_BEGIN(PluginWrapper.h)
namespace Vamp {
namespace HostExt {
/**
- * \class PluginWrapper PluginWrapper.h <vamp-sdk/hostext/PluginWrapper.h>
+ * \class PluginWrapper PluginWrapper.h <vamp-hostsdk/PluginWrapper.h>
*
* PluginWrapper is a simple base class for adapter plugins. It takes
* a pointer to a "to be wrapped" Vamp plugin on construction, and
@@ -94,6 +97,30 @@ public:
FeatureSet getRemainingFeatures();
+ /**
+ * Return a pointer to the plugin wrapper of type WrapperType
+ * surrounding this wrapper's plugin, if present.
+ *
+ * This is useful in situations where a plugin is wrapped by
+ * multiple different wrappers (one inside another) and the host
+ * wants to call some wrapper-specific function on one of the
+ * layers without having to care about the order in which they are
+ * wrapped. For example, the plugin returned by
+ * PluginLoader::loadPlugin may have more than one wrapper; if the
+ * host wanted to query or fine-tune some property of one of them,
+ * it would be hard to do so without knowing the order of the
+ * wrappers. This function therefore gives direct access to the
+ * wrapper of a particular type.
+ */
+ template <typename WrapperType>
+ WrapperType *getWrapper() {
+ WrapperType *w = dynamic_cast<WrapperType *>(this);
+ if (w) return w;
+ PluginWrapper *pw = dynamic_cast<PluginWrapper *>(m_plugin);
+ if (pw) return pw->getWrapper<WrapperType>();
+ return 0;
+ }
+
protected:
PluginWrapper(Plugin *plugin); // I take ownership of plugin
Plugin *m_plugin;
@@ -103,4 +130,6 @@ protected:
}
+_VAMP_SDK_HOSTSPACE_END(PluginWrapper.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/RealTime.h b/libs/vamp-sdk/vamp-hostsdk/RealTime.h
new file mode 100644
index 0000000000..d789b6a1ac
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/RealTime.h
@@ -0,0 +1,46 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_HOSTSDK_REALTIME_H_
+#define _VAMP_HOSTSDK_REALTIME_H_
+
+// Do not include vamp-sdk/RealTime.h directly from host code. Always
+// use this header instead.
+
+#include "hostguard.h"
+#include <vamp-sdk/RealTime.h>
+
+#endif
diff --git a/libs/vamp-sdk/vamp-hostsdk/hostguard.h b/libs/vamp-sdk/vamp-hostsdk/hostguard.h
new file mode 100644
index 0000000000..3698d84cd7
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/hostguard.h
@@ -0,0 +1,69 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_HOSTSDK_HOSTGUARD_H_
+#define _VAMP_HOSTSDK_HOSTGUARD_H_
+
+#ifdef _VAMP_IN_PLUGINSDK
+#error You have included headers from both vamp-sdk and vamp-hostsdk in the same source file. Please include only vamp-sdk headers in plugin code, and only vamp-hostsdk headers in host code.
+#else
+
+#define _VAMP_IN_HOSTSDK
+
+#ifdef _VAMP_NO_HOST_NAMESPACE
+#define _VAMP_SDK_HOSTSPACE_BEGIN(h)
+#define _VAMP_SDK_HOSTSPACE_END(h)
+#define _VAMP_SDK_PLUGSPACE_BEGIN(h)
+#define _VAMP_SDK_PLUGSPACE_END(h)
+#else
+#define _VAMP_SDK_HOSTSPACE_BEGIN(h) \
+ namespace _VampHost {
+
+#define _VAMP_SDK_HOSTSPACE_END(h) \
+ } \
+ using namespace _VampHost;
+#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \
+ namespace _VampHost {
+
+#define _VAMP_SDK_PLUGSPACE_END(h) \
+ } \
+ using namespace _VampHost;
+#endif
+
+#endif
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-hostsdk/vamp-hostsdk.h b/libs/vamp-sdk/vamp-hostsdk/vamp-hostsdk.h
new file mode 100644
index 0000000000..f32583d549
--- /dev/null
+++ b/libs/vamp-sdk/vamp-hostsdk/vamp-hostsdk.h
@@ -0,0 +1,53 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_HOSTSDK_SINGLE_INCLUDE_H_
+#define _VAMP_HOSTSDK_SINGLE_INCLUDE_H_
+
+#include "PluginBase.h"
+#include "PluginBufferingAdapter.h"
+#include "PluginChannelAdapter.h"
+#include "Plugin.h"
+#include "PluginHostAdapter.h"
+#include "PluginInputDomainAdapter.h"
+#include "PluginLoader.h"
+#include "PluginSummarisingAdapter.h"
+#include "PluginWrapper.h"
+#include "RealTime.h"
+
+#endif
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/Plugin.h b/libs/vamp-sdk/vamp-sdk/Plugin.h
index 159bf4fac6..4709b19b67 100644
--- a/libs/vamp-sdk/vamp-sdk/Plugin.h
+++ b/libs/vamp-sdk/vamp-sdk/Plugin.h
@@ -34,16 +34,19 @@
authorization.
*/
-#ifndef _VAMP_PLUGIN_H_
-#define _VAMP_PLUGIN_H_
-
-#include "PluginBase.h"
-#include "RealTime.h"
+#ifndef _VAMP_SDK_PLUGIN_H_
+#define _VAMP_SDK_PLUGIN_H_
#include <string>
#include <vector>
#include <map>
+#include "PluginBase.h"
+#include "RealTime.h"
+
+#include "plugguard.h"
+_VAMP_SDK_PLUGSPACE_BEGIN(Plugin.h)
+
namespace Vamp {
/**
@@ -200,7 +203,7 @@ public:
/**
* The name of the output, in computer-usable form. Should be
* reasonably short and without whitespace or punctuation, using
- * the characters [a-zA-Z0-9_] only.
+ * the characters [a-zA-Z0-9_-] only.
* Example: "zero_crossing_count"
*/
std::string identifier;
@@ -304,6 +307,16 @@ public:
* this to zero if that behaviour is not desired.
*/
float sampleRate;
+
+ /**
+ * True if the returned results for this output are known to
+ * have a duration field.
+ */
+ bool hasDuration;
+
+ OutputDescriptor() : // defaults for mandatory non-class-type members
+ hasFixedBinCount(false), hasKnownExtents(false), isQuantized(false),
+ sampleType(OneSamplePerStep), hasDuration(false) { }
};
typedef std::vector<OutputDescriptor> OutputList;
@@ -319,17 +332,34 @@ public:
{
/**
* True if an output feature has its own timestamp. This is
- * mandatory if the output has VariableSampleRate, and is
- * likely to be disregarded otherwise.
+ * mandatory if the output has VariableSampleRate, optional if
+ * the output has FixedSampleRate, and unused if the output
+ * has OneSamplePerStep.
*/
bool hasTimestamp;
/**
* Timestamp of the output feature. This is mandatory if the
- * output has VariableSampleRate, and is likely to be
- * disregarded otherwise. Undefined if hasTimestamp is false.
+ * output has VariableSampleRate or if the output has
+ * FixedSampleRate and hasTimestamp is true, and unused
+ * otherwise.
*/
RealTime timestamp;
+
+ /**
+ * True if an output feature has a specified duration. This
+ * is optional if the output has VariableSampleRate or
+ * FixedSampleRate, and and unused if the output has
+ * OneSamplePerStep.
+ */
+ bool hasDuration;
+
+ /**
+ * Duration of the output feature. This is mandatory if the
+ * output has VariableSampleRate or FixedSampleRate and
+ * hasDuration is true, and unused otherwise.
+ */
+ RealTime duration;
/**
* Results for a single sample of this feature. If the output
@@ -342,9 +372,13 @@ public:
* Label for the sample of this feature.
*/
std::string label;
+
+ Feature() : // defaults for mandatory non-class-type members
+ hasTimestamp(false), hasDuration(false) { }
};
typedef std::vector<Feature> FeatureList;
+
typedef std::map<int, FeatureList> FeatureSet; // key is output no
/**
@@ -353,9 +387,9 @@ public:
* If the plugin's inputDomain is TimeDomain, inputBuffers will
* point to one array of floats per input channel, and each of
* these arrays will contain blockSize consecutive audio samples
- * (the host will zero-pad as necessary). The timestamp will be
- * the real time in seconds of the start of the supplied block of
- * samples.
+ * (the host will zero-pad as necessary). The timestamp in this
+ * case will be the real time in seconds of the start of the
+ * supplied block of samples.
*
* If the plugin's inputDomain is FrequencyDomain, inputBuffers
* will point to one array of floats per input channel, and each
@@ -399,6 +433,8 @@ protected:
}
+_VAMP_SDK_PLUGSPACE_END(Plugin.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-sdk/PluginAdapter.h b/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
index bfc97508eb..dafd532a3b 100644
--- a/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
+++ b/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
@@ -37,11 +37,13 @@
#ifndef _VAMP_PLUGIN_ADAPTER_H_
#define _VAMP_PLUGIN_ADAPTER_H_
+#include <map>
#include <vamp/vamp.h>
#include "Plugin.h"
-#include <map>
+#include "plugguard.h"
+_VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.h)
namespace Vamp {
@@ -113,5 +115,7 @@ protected:
}
+_VAMP_SDK_PLUGSPACE_END(PluginAdapter.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-sdk/PluginBase.h b/libs/vamp-sdk/vamp-sdk/PluginBase.h
index 38d2b49904..147ffdc153 100644
--- a/libs/vamp-sdk/vamp-sdk/PluginBase.h
+++ b/libs/vamp-sdk/vamp-sdk/PluginBase.h
@@ -34,13 +34,18 @@
authorization.
*/
-#ifndef _VAMP_PLUGIN_BASE_H_
-#define _VAMP_PLUGIN_BASE_H_
+#ifndef _VAMP_SDK_PLUGIN_BASE_H_
+#define _VAMP_SDK_PLUGIN_BASE_H_
#include <string>
#include <vector>
-#define VAMP_SDK_VERSION "1.1"
+#define VAMP_SDK_VERSION "2.0"
+#define VAMP_SDK_MAJOR_VERSION 2
+#define VAMP_SDK_MINOR_VERSION 0
+
+#include "plugguard.h"
+_VAMP_SDK_PLUGSPACE_BEGIN(PluginBase.h)
namespace Vamp {
@@ -64,12 +69,12 @@ public:
/**
* Get the Vamp API compatibility level of the plugin.
*/
- virtual unsigned int getVampApiVersion() const { return 1; }
+ virtual unsigned int getVampApiVersion() const { return 2; }
/**
* Get the computer-usable name of the plugin. This should be
* reasonably short and contain no whitespace or punctuation
- * characters. It may only contain the characters [a-zA-Z0-9_].
+ * characters. It may only contain the characters [a-zA-Z0-9_-].
* This is the authoritative way for a program to identify a
* plugin within a given library.
*
@@ -127,7 +132,7 @@ public:
/**
* The name of the parameter, in computer-usable form. Should
* be reasonably short, and may only contain the characters
- * [a-zA-Z0-9_].
+ * [a-zA-Z0-9_-].
*/
std::string identifier;
@@ -190,6 +195,9 @@ public:
* encoded in the names.
*/
std::vector<std::string> valueNames;
+
+ ParameterDescriptor() : // the defaults are invalid: you must set them
+ minValue(0), maxValue(0), defaultValue(0), isQuantized(false) { }
};
typedef std::vector<ParameterDescriptor> ParameterList;
@@ -249,4 +257,6 @@ public:
}
+_VAMP_SDK_PLUGSPACE_END(PluginBase.h)
+
#endif
diff --git a/libs/vamp-sdk/vamp-sdk/RealTime.h b/libs/vamp-sdk/vamp-sdk/RealTime.h
index 6b88ed53f0..297c4ad524 100644
--- a/libs/vamp-sdk/vamp-sdk/RealTime.h
+++ b/libs/vamp-sdk/vamp-sdk/RealTime.h
@@ -51,6 +51,9 @@
struct timeval;
#endif
+#include "plugguard.h"
+_VAMP_SDK_PLUGSPACE_BEGIN(RealTime.h)
+
namespace Vamp {
/**
@@ -158,5 +161,7 @@ struct RealTime
std::ostream &operator<<(std::ostream &out, const RealTime &rt);
}
+
+_VAMP_SDK_PLUGSPACE_END(RealTime.h)
#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.h
deleted file mode 100644
index 24ca6f8db8..0000000000
--- a/libs/vamp-sdk/vamp-sdk/hostext/PluginBufferingAdapter.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
-
-/*
- Vamp
-
- An API for audio analysis and feature extraction plugins.
-
- Centre for Digital Music, Queen Mary, University of London.
- Copyright 2006-2007 Chris Cannam and QMUL.
- This file by Mark Levy, Copyright 2007 QMUL.
-
- 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 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.
-
- Except as contained in this notice, the names of the Centre for
- Digital Music; Queen Mary, University of London; and Chris Cannam
- shall not be used in advertising or otherwise to promote the sale,
- use or other dealings in this Software without prior written
- authorization.
-*/
-
-#ifndef _VAMP_PLUGIN_BUFFERING_ADAPTER_H_
-#define _VAMP_PLUGIN_BUFFERING_ADAPTER_H_
-
-#include "PluginWrapper.h"
-
-namespace Vamp {
-
-namespace HostExt {
-
-/**
- * \class PluginBufferingAdapter PluginBufferingAdapter.h <vamp-sdk/hostext/PluginBufferingAdapter.h>
- *
- * PluginBufferingAdapter is a Vamp plugin adapter that allows plugins
- * to be used by a host supplying an audio stream in non-overlapping
- * buffers of arbitrary size.
- *
- * A host using PluginBufferingAdapter may ignore the preferred step
- * and block size reported by the plugin, and still expect the plugin
- * to run. The value of blockSize and stepSize passed to initialise
- * should be the size of the buffer which the host will supply; the
- * stepSize should be equal to the blockSize.
- *
- * If the internal step size used for the plugin differs from that
- * supplied by the host, the adapter will modify the sample rate
- * specifications for the plugin outputs (setting them all to
- * VariableSampleRate) and set timestamps on the output features for
- * outputs that formerly used a different sample rate specification.
- * This is necessary in order to obtain correct time stamping.
- *
- * In other respects, the PluginBufferingAdapter behaves identically
- * to the plugin that it wraps. The wrapped plugin will be deleted
- * when the wrapper is deleted.
- */
-
-class PluginBufferingAdapter : public PluginWrapper
-{
-public:
- PluginBufferingAdapter(Plugin *plugin); // I take ownership of plugin
- virtual ~PluginBufferingAdapter();
-
- bool initialise(size_t channels, size_t stepSize, size_t blockSize);
-
- size_t getPreferredStepSize() const;
-
- OutputList getOutputDescriptors() const;
-
- void reset();
-
- FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
-
- FeatureSet getRemainingFeatures();
-
-protected:
- class Impl;
- Impl *m_impl;
-};
-
-}
-
-}
-
-#endif
diff --git a/libs/vamp-sdk/vamp-sdk/plugguard.h b/libs/vamp-sdk/vamp-sdk/plugguard.h
new file mode 100644
index 0000000000..311dd488e0
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/plugguard.h
@@ -0,0 +1,98 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_SDK_PLUGGUARD_H_
+#define _VAMP_SDK_PLUGGUARD_H_
+
+/**
+ * Normal usage should be:
+ *
+ * - Plugins include vamp-sdk/Plugin.h or vamp-sdk/PluginBase.h.
+ * These files include this header, which specifies an appropriate
+ * namespace for the plugin classes to avoid any risk of conflict
+ * with non-plugin class implementations in the host on load.
+ *
+ * - Hosts include vamp-hostsdk/Plugin.h, vamp-hostsdk/PluginBase.h,
+ * vamp-hostsdk/PluginHostAdapter, vamp-hostsdk/PluginLoader.h etc.
+ * These files include vamp-hostsdk/hostguard.h, which makes a note
+ * that we are in a host. A file such as vamp-hostsdk/Plugin.h
+ * then simply includes vamp-sdk/Plugin.h, and this guard header
+ * takes notice of the fact that it has been included from a host
+ * and leaves the plugin namespace unset.
+ *
+ * Problems will occur when a host includes files directly from the
+ * vamp-sdk directory. There are two reasons this might happen:
+ * mistake, perhaps owing to ignorance of the fact that this isn't
+ * allowed (particularly since it was the normal mechanism in v1 of
+ * the SDK); and a wish to incorporate plugin code directly into the
+ * host rather than having to load it.
+ *
+ * What if the host does include a vamp-sdk header by mistake? We can
+ * catch it if it's included before something from vamp-hostsdk. If
+ * it's included after something from vamp-hostsdk, it will work OK
+ * anyway. The remaining problem case is where nothing from
+ * vamp-hostsdk is included in the same file. We can't catch that.
+ */
+
+#ifndef _VAMP_IN_HOSTSDK
+
+#define _VAMP_IN_PLUGINSDK 1
+
+#ifdef _VAMP_NO_PLUGIN_NAMESPACE
+#define _VAMP_SDK_PLUGSPACE_BEGIN(h)
+#define _VAMP_SDK_PLUGSPACE_END(h)
+#else
+#ifdef _VAMP_PLUGIN_IN_HOST_NAMESPACE
+#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \
+ namespace _VampHost {
+
+#define _VAMP_SDK_PLUGSPACE_END(h) \
+ } \
+ using namespace _VampHost;
+#else
+#define _VAMP_SDK_PLUGSPACE_BEGIN(h) \
+ namespace _VampPlugin {
+
+#define _VAMP_SDK_PLUGSPACE_END(h) \
+ } \
+ using namespace _VampPlugin;
+#endif
+#endif
+
+#endif
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-sdk/vamp-sdk.h b/libs/vamp-sdk/vamp-sdk/vamp-sdk.h
new file mode 100644
index 0000000000..3ac2f8bc05
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/vamp-sdk.h
@@ -0,0 +1,46 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ 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 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.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_SDK_SINGLE_INCLUDE_H_
+#define _VAMP_SDK_SINGLE_INCLUDE_H_
+
+#include "PluginBase.h"
+#include "Plugin.h"
+#include "RealTime.h"
+
+#endif
+
+
diff --git a/libs/vamp-sdk/vamp/vamp.h b/libs/vamp-sdk/vamp/vamp.h
index 4f0145ab59..08a83ee6ac 100644
--- a/libs/vamp-sdk/vamp/vamp.h
+++ b/libs/vamp-sdk/vamp/vamp.h
@@ -50,7 +50,7 @@ extern "C" {
* See also the vampApiVersion field in the plugin descriptor, and the
* hostApiVersion argument to the vampGetPluginDescriptor function.
*/
-#define VAMP_API_VERSION 1
+#define VAMP_API_VERSION 2
/**
* C language API for Vamp plugins.
@@ -160,6 +160,15 @@ typedef struct _VampOutputDescriptor
"Resolution" of result, if sampleType is vampVariableSampleRate. */
float sampleRate;
+ /** 1 if the returned results for this output are known to have a
+ duration field.
+
+ This field is new in Vamp API version 2; it must not be tested
+ for plugins that report an older API version in their plugin
+ descriptor.
+ */
+ int hasDuration;
+
} VampOutputDescriptor;
typedef struct _VampFeature
@@ -184,13 +193,46 @@ typedef struct _VampFeature
} VampFeature;
+typedef struct _VampFeatureV2
+{
+ /** 1 if the feature has a duration. */
+ int hasDuration;
+
+ /** Seconds component of duratiion. */
+ int durationSec;
+
+ /** Nanoseconds component of duration. */
+ int durationNsec;
+
+} VampFeatureV2;
+
+typedef union _VampFeatureUnion
+{
+ // sizeof(featureV1) >= sizeof(featureV2) for backward compatibility
+ VampFeature v1;
+ VampFeatureV2 v2;
+
+} VampFeatureUnion;
+
typedef struct _VampFeatureList
{
/** Number of features in this feature list. */
unsigned int featureCount;
- /** Features in this feature list. May be NULL if featureCount is zero. */
- VampFeature *features;
+ /** Features in this feature list. May be NULL if featureCount is
+ zero.
+
+ If present, this array must contain featureCount feature
+ structures for a Vamp API version 1 plugin, or 2*featureCount
+ feature unions for a Vamp API version 2 plugin.
+
+ The features returned by an API version 2 plugin must consist
+ of the same feature structures as in API version 1 for the
+ first featureCount array elements, followed by featureCount
+ unions that contain VampFeatureV2 structures (or NULL pointers
+ if no V2 feature structures are present).
+ */
+ VampFeatureUnion *features;
} VampFeatureList;
@@ -289,7 +331,7 @@ typedef struct _VampPluginDescriptor
handle, or releaseOutputDescriptor for this descriptor. Host
must call releaseOutputDescriptor after use. */
VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle,
- unsigned int);
+ unsigned int);
/** Destroy a descriptor for a feature output. */
void (*releaseOutputDescriptor)(VampOutputDescriptor *);
@@ -312,6 +354,7 @@ typedef struct _VampPluginDescriptor
} VampPluginDescriptor;
+
/** Get the descriptor for a given plugin index in this library.
Return NULL if the index is outside the range of valid indices for
this plugin library.
@@ -324,10 +367,16 @@ typedef struct _VampPluginDescriptor
field for its actual compatibility level, the host should be able
to do the right thing with it: use it if possible, discard it
otherwise.
+
+ This is the only symbol that a Vamp plugin actually needs to
+ export from its shared object; all others can be hidden. See the
+ accompanying documentation for notes on how to achieve this with
+ certain compilers.
*/
const VampPluginDescriptor *vampGetPluginDescriptor
(unsigned int hostApiVersion, unsigned int index);
+
/** Function pointer type for vampGetPluginDescriptor. */
typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction)
(unsigned int, unsigned int);