mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
upgrade VAMP SDK to latest (or newer) version
git-svn-id: svn://localhost/ardour2/branches/3.0@9030 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
3deba1921b
commit
730cdb38bc
16 changed files with 329 additions and 90 deletions
|
|
@ -6,8 +6,8 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
This file by Mark Levy and Chris Cannam, Copyright 2007-2009 QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "vamp-hostsdk/PluginBufferingAdapter.h"
|
||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
|
@ -652,6 +653,14 @@ PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
|
|||
|
||||
FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
|
||||
|
||||
PluginWrapper *wrapper = dynamic_cast<PluginWrapper *>(m_plugin);
|
||||
RealTime adjustment;
|
||||
if (wrapper) {
|
||||
PluginInputDomainAdapter *ida =
|
||||
wrapper->getWrapper<PluginInputDomainAdapter>();
|
||||
if (ida) adjustment = ida->getTimestampAdjustment();
|
||||
}
|
||||
|
||||
for (FeatureSet::iterator iter = featureSet.begin();
|
||||
iter != featureSet.end(); ++iter) {
|
||||
|
||||
|
|
@ -667,14 +676,14 @@ PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
|
|||
|
||||
case OutputDescriptor::OneSamplePerStep:
|
||||
// use our internal timestamp, always
|
||||
featureList[i].timestamp = timestamp;
|
||||
featureList[i].timestamp = timestamp + adjustment;
|
||||
featureList[i].hasTimestamp = true;
|
||||
break;
|
||||
|
||||
case OutputDescriptor::FixedSampleRate:
|
||||
// use our internal timestamp if feature lacks one
|
||||
if (!featureList[i].hasTimestamp) {
|
||||
featureList[i].timestamp = timestamp;
|
||||
featureList[i].timestamp = timestamp + adjustment;
|
||||
featureList[i].hasTimestamp = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@
|
|||
#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)
|
||||
#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 2 )
|
||||
#error Unexpected version of Vamp SDK header included
|
||||
#endif
|
||||
|
||||
_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
This file is based in part on Don Cross's public domain FFT
|
||||
implementation.
|
||||
|
|
@ -83,24 +83,33 @@ public:
|
|||
~Impl();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
|
||||
void setProcessTimestampMethod(ProcessTimestampMethod m);
|
||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||
|
||||
RealTime getTimestampAdjustment() const;
|
||||
|
||||
protected:
|
||||
Plugin *m_plugin;
|
||||
float m_inputSampleRate;
|
||||
int m_channels;
|
||||
int m_stepSize;
|
||||
int m_blockSize;
|
||||
float **m_freqbuf;
|
||||
|
||||
double *m_ri;
|
||||
double *m_window;
|
||||
|
||||
ProcessTimestampMethod m_method;
|
||||
int m_processCount;
|
||||
float **m_shiftBuffers;
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_plan m_plan;
|
||||
fftw_complex *m_cbuf;
|
||||
|
|
@ -111,6 +120,9 @@ protected:
|
|||
double *ri, double *ii, double *ro, double *io);
|
||||
#endif
|
||||
|
||||
FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
|
||||
|
||||
size_t makeBlockSizeAcceptable(size_t) const;
|
||||
};
|
||||
|
||||
|
|
@ -131,6 +143,12 @@ PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t bl
|
|||
return m_impl->initialise(channels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::reset()
|
||||
{
|
||||
m_impl->reset();
|
||||
}
|
||||
|
||||
Plugin::InputDomain
|
||||
PluginInputDomainAdapter::getInputDomain() const
|
||||
{
|
||||
|
|
@ -155,6 +173,18 @@ PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime tim
|
|||
return m_impl->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
|
||||
{
|
||||
m_impl->setProcessTimestampMethod(m);
|
||||
}
|
||||
|
||||
PluginInputDomainAdapter::ProcessTimestampMethod
|
||||
PluginInputDomainAdapter::getProcessTimestampMethod() const
|
||||
{
|
||||
return m_impl->getProcessTimestampMethod();
|
||||
}
|
||||
|
||||
RealTime
|
||||
PluginInputDomainAdapter::getTimestampAdjustment() const
|
||||
{
|
||||
|
|
@ -166,10 +196,14 @@ PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
|||
m_plugin(plugin),
|
||||
m_inputSampleRate(inputSampleRate),
|
||||
m_channels(0),
|
||||
m_stepSize(0),
|
||||
m_blockSize(0),
|
||||
m_freqbuf(0),
|
||||
m_ri(0),
|
||||
m_window(0),
|
||||
m_method(ShiftTimestamp),
|
||||
m_processCount(0),
|
||||
m_shiftBuffers(0),
|
||||
#ifdef HAVE_FFTW3
|
||||
m_plan(0),
|
||||
m_cbuf(0)
|
||||
|
|
@ -184,6 +218,13 @@ PluginInputDomainAdapter::Impl::~Impl()
|
|||
{
|
||||
// the adapter will delete the plugin
|
||||
|
||||
if (m_shiftBuffers) {
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
delete[] m_shiftBuffers[c];
|
||||
}
|
||||
delete[] m_shiftBuffers;
|
||||
}
|
||||
|
||||
if (m_channels > 0) {
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
delete[] m_freqbuf[c];
|
||||
|
|
@ -215,6 +256,7 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
|||
{
|
||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||
|
||||
m_stepSize = int(stepSize);
|
||||
m_blockSize = int(blockSize);
|
||||
m_channels = int(channels);
|
||||
|
||||
|
|
@ -222,12 +264,12 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
|||
}
|
||||
|
||||
if (blockSize < 2) {
|
||||
std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not supported" << std::endl;
|
||||
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blockSize & (blockSize-1)) {
|
||||
std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
|
||||
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +293,7 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
|||
delete[] m_window;
|
||||
}
|
||||
|
||||
m_stepSize = int(stepSize);
|
||||
m_blockSize = int(blockSize);
|
||||
m_channels = int(channels);
|
||||
|
||||
|
|
@ -275,9 +318,18 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
|||
m_io = new double[m_blockSize];
|
||||
#endif
|
||||
|
||||
m_processCount = 0;
|
||||
|
||||
return m_plugin->initialise(channels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::Impl::reset()
|
||||
{
|
||||
m_processCount = 0;
|
||||
m_plugin->reset();
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginInputDomainAdapter::Impl::getPreferredStepSize() const
|
||||
{
|
||||
|
|
@ -311,7 +363,7 @@ PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
|||
{
|
||||
if (blockSize < 2) {
|
||||
|
||||
std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not" << std::endl
|
||||
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
|
||||
<< "supported, increasing from " << blockSize << " to 2" << std::endl;
|
||||
blockSize = 2;
|
||||
|
||||
|
|
@ -340,7 +392,7 @@ PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
|||
nearest = nearest*2;
|
||||
}
|
||||
|
||||
std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
|
||||
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
|
||||
blockSize = nearest;
|
||||
|
||||
#endif
|
||||
|
|
@ -354,12 +406,26 @@ PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
|||
{
|
||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||
return RealTime::zeroTime;
|
||||
} else if (m_method == ShiftData || m_method == NoShift) {
|
||||
return RealTime::zeroTime;
|
||||
} else {
|
||||
return RealTime::frame2RealTime
|
||||
(m_blockSize/2, int(m_inputSampleRate + 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
|
||||
{
|
||||
m_method = m;
|
||||
}
|
||||
|
||||
PluginInputDomainAdapter::ProcessTimestampMethod
|
||||
PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
|
||||
{
|
||||
return m_method;
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
|
|
@ -368,53 +434,20 @@ PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
|||
return m_plugin->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
// The timestamp supplied should be (according to the Vamp::Plugin
|
||||
// spec) the time of the start of the time-domain input block.
|
||||
// However, we want to pass to the plugin an FFT output calculated
|
||||
// from the block of samples _centred_ on that timestamp.
|
||||
//
|
||||
// We have two options:
|
||||
//
|
||||
// 1. Buffer the input, calculating the fft of the values at the
|
||||
// passed-in block minus blockSize/2 rather than starting at the
|
||||
// passed-in block. So each time we call process on the plugin,
|
||||
// we are passing in the same timestamp as was passed to our own
|
||||
// process plugin, but not (the frequency domain representation
|
||||
// of) the same set of samples. Advantages: avoids confusion in
|
||||
// the host by ensuring the returned values have timestamps
|
||||
// comparable with that passed in to this function (in fact this
|
||||
// is pretty much essential for one-value-per-block outputs);
|
||||
// consistent with hosts such as SV that deal with the
|
||||
// frequency-domain transform themselves. Disadvantages: means
|
||||
// making the not necessarily correct assumption that the samples
|
||||
// preceding the first official block are all zero (or some other
|
||||
// known value).
|
||||
//
|
||||
// 2. Increase the passed-in timestamps by half the blocksize. So
|
||||
// when we call process, we are passing in the frequency domain
|
||||
// representation of the same set of samples as passed to us, but
|
||||
// with a different timestamp. Advantages: simplicity; avoids
|
||||
// iffy assumption mentioned above. Disadvantages: inconsistency
|
||||
// with SV in cases where stepSize != blockSize/2; potential
|
||||
// confusion arising from returned timestamps being calculated
|
||||
// from the adjusted input timestamps rather than the original
|
||||
// ones (and inaccuracy where the returned timestamp is implied,
|
||||
// as in one-value-per-block).
|
||||
//
|
||||
// Neither way is ideal, but I don't think either is strictly
|
||||
// incorrect either. I think this is just a case where the same
|
||||
// plugin can legitimately produce differing results from the same
|
||||
// input data, depending on how that data is packaged.
|
||||
//
|
||||
// We'll go for option 2, adjusting the timestamps. Note in
|
||||
// particular that this means some results can differ from those
|
||||
// produced by SV.
|
||||
|
||||
// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
|
||||
if (m_method == ShiftTimestamp || m_method == NoShift) {
|
||||
return processShiftingTimestamp(inputBuffers, timestamp);
|
||||
} else {
|
||||
return processShiftingData(inputBuffers, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
{
|
||||
if (m_method == ShiftTimestamp) {
|
||||
timestamp = timestamp + getTimestampAdjustment();
|
||||
|
||||
// std::cerr << " to " << timestamp << std::endl;
|
||||
}
|
||||
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
|
||||
|
|
@ -430,29 +463,87 @@ PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
|||
}
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
|
||||
fftw_execute(m_plan);
|
||||
|
||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||
m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
|
||||
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
|
||||
|
||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||
m_freqbuf[c][i * 2] = float(m_ro[i]);
|
||||
m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_plugin->process(m_freqbuf, timestamp);
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
{
|
||||
if (m_processCount == 0) {
|
||||
if (!m_shiftBuffers) {
|
||||
m_shiftBuffers = new float *[m_channels];
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
|
||||
}
|
||||
}
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
|
||||
m_shiftBuffers[c][i] = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
|
||||
m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
|
||||
}
|
||||
for (int i = 0; i < m_blockSize; ++i) {
|
||||
m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
|
||||
for (int i = 0; i < m_blockSize; ++i) {
|
||||
m_ri[i] = double(m_shiftBuffers[c][i]) * m_window[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_blockSize/2; ++i) {
|
||||
// FFT shift
|
||||
double value = m_ri[i];
|
||||
m_ri[i] = m_ri[i + m_blockSize/2];
|
||||
m_ri[i + m_blockSize/2] = value;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_execute(m_plan);
|
||||
|
||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||
m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
|
||||
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
|
||||
}
|
||||
#else
|
||||
fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
|
||||
|
||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||
m_freqbuf[c][i * 2] = float(m_ro[i]);
|
||||
m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
++m_processCount;
|
||||
|
||||
return m_plugin->process(m_freqbuf, timestamp);
|
||||
}
|
||||
|
||||
#ifndef HAVE_FFTW3
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
@ -270,26 +270,39 @@ PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
|
|||
(handle, "vampGetPluginDescriptor");
|
||||
|
||||
if (!fn) {
|
||||
if (forPlugin != "") {
|
||||
cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
|
||||
<< fullPath << "\"" << endl;
|
||||
}
|
||||
unloadLibrary(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
const VampPluginDescriptor *descriptor = 0;
|
||||
bool found = false;
|
||||
|
||||
while ((descriptor = fn(VAMP_API_VERSION, index))) {
|
||||
++index;
|
||||
if (identifier != "") {
|
||||
if (descriptor->identifier != identifier) continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
PluginKey key = composePluginKey(*fi, descriptor->identifier);
|
||||
// std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
|
||||
|
||||
if (m_pluginLibraryNameMap.find(key) ==
|
||||
m_pluginLibraryNameMap.end()) {
|
||||
m_pluginLibraryNameMap[key] = fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && forPlugin != "") {
|
||||
cerr << "Vamp::HostExt::PluginLoader: Plugin \""
|
||||
<< identifier << "\" not found in library \""
|
||||
<< fullPath << "\"" << endl;
|
||||
}
|
||||
|
||||
unloadLibrary(handle);
|
||||
}
|
||||
}
|
||||
|
|
@ -345,9 +358,11 @@ PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
|
|||
{
|
||||
if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
|
||||
if (m_allPluginsEnumerated) return "";
|
||||
cerr << "plug not found enumerate" << endl;
|
||||
enumeratePlugins(plugin);
|
||||
}
|
||||
if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
|
||||
cerr << "plug not found enumerate" << endl;
|
||||
return "";
|
||||
}
|
||||
return m_pluginLibraryNameMap[plugin];
|
||||
|
|
@ -365,7 +380,10 @@ PluginLoader::Impl::loadPlugin(PluginKey key,
|
|||
}
|
||||
|
||||
string fullPath = getLibraryPathForPlugin(key);
|
||||
if (fullPath == "") return 0;
|
||||
if (fullPath == "") {
|
||||
std::cerr << "Vamp::HostExt::PluginLoader: No library found in Vamp path for plugin \"" << key << "\"" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *handle = loadLibrary(fullPath);
|
||||
if (!handle) return 0;
|
||||
|
|
@ -375,6 +393,8 @@ PluginLoader::Impl::loadPlugin(PluginKey key,
|
|||
(handle, "vampGetPluginDescriptor");
|
||||
|
||||
if (!fn) {
|
||||
cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
|
||||
<< fullPath << "\"" << endl;
|
||||
unloadLibrary(handle);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -513,7 +533,21 @@ PluginLoader::Impl::loadLibrary(string path)
|
|||
{
|
||||
void *handle = 0;
|
||||
#ifdef _WIN32
|
||||
#ifdef UNICODE
|
||||
int len = path.length(); // cannot be more wchars than length in bytes of utf8 string
|
||||
wchar_t *buffer = new wchar_t[len];
|
||||
int rv = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), len, buffer, len);
|
||||
if (rv <= 0) {
|
||||
cerr << "Vamp::HostExt::PluginLoader: Unable to convert library path \""
|
||||
<< path << "\" to wide characters " << endl;
|
||||
delete[] buffer;
|
||||
return handle;
|
||||
}
|
||||
handle = LoadLibrary(buffer);
|
||||
delete[] buffer;
|
||||
#else
|
||||
handle = LoadLibrary(path.c_str());
|
||||
#endif
|
||||
if (!handle) {
|
||||
cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
|
||||
<< path << "\"" << endl;
|
||||
|
|
@ -564,8 +598,41 @@ PluginLoader::Impl::listFiles(string dir, string extension)
|
|||
vector<string> files;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
string expression = dir + "\\*." + extension;
|
||||
#ifdef UNICODE
|
||||
int len = expression.length(); // cannot be more wchars than length in bytes of utf8 string
|
||||
wchar_t *buffer = new wchar_t[len];
|
||||
int rv = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), len, buffer, len);
|
||||
if (rv <= 0) {
|
||||
cerr << "Vamp::HostExt::PluginLoader: Unable to convert wildcard path \""
|
||||
<< expression << "\" to wide characters" << endl;
|
||||
delete[] buffer;
|
||||
return files;
|
||||
}
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE fh = FindFirstFile(buffer, &data);
|
||||
if (fh == INVALID_HANDLE_VALUE) {
|
||||
delete[] buffer;
|
||||
return files;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
while (ok) {
|
||||
wchar_t *fn = data.cFileName;
|
||||
int wlen = wcslen(fn);
|
||||
int maxlen = wlen * 6;
|
||||
char *conv = new char[maxlen];
|
||||
int rv = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, maxlen, 0, 0);
|
||||
if (rv > 0) {
|
||||
files.push_back(conv);
|
||||
}
|
||||
delete[] conv;
|
||||
ok = FindNextFile(fh, &data);
|
||||
}
|
||||
|
||||
FindClose(fh);
|
||||
delete[] buffer;
|
||||
#else
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE fh = FindFirstFile(expression.c_str(), &data);
|
||||
if (fh == INVALID_HANDLE_VALUE) return files;
|
||||
|
|
@ -577,7 +644,7 @@ PluginLoader::Impl::listFiles(string dir, string extension)
|
|||
}
|
||||
|
||||
FindClose(fh);
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
size_t extlen = extension.length();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
#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)
|
||||
#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 2 )
|
||||
#error Unexpected version of Vamp SDK header included
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -169,6 +169,11 @@ PluginAdapterBase::Impl::getDescriptor()
|
|||
|
||||
Plugin *plugin = m_base->createPlugin(48000);
|
||||
|
||||
if (!plugin) {
|
||||
std::cerr << "PluginAdapterBase::Impl::getDescriptor: Failed to create plugin" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
|
||||
std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
|
||||
<< "API version " << plugin->getVampApiVersion()
|
||||
|
|
@ -583,7 +588,7 @@ PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
|
|||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList */*fs*/)
|
||||
PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
@ -91,6 +91,7 @@ public:
|
|||
virtual ~PluginInputDomainAdapter();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
|
||||
InputDomain getInputDomain() const;
|
||||
|
||||
|
|
@ -99,6 +100,63 @@ public:
|
|||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
|
||||
/**
|
||||
* ProcessTimestampMethod determines how the
|
||||
* PluginInputDomainAdapter handles timestamps for the data passed
|
||||
* to the process() function of the plugin it wraps, in the case
|
||||
* where the plugin is expecting frequency-domain data.
|
||||
*
|
||||
* The Vamp specification requires that the timestamp passed to
|
||||
* the plugin for frequency-domain input should be that of the
|
||||
* centre of the processing block, rather than the start as is the
|
||||
* case for time-domain input.
|
||||
*
|
||||
* Since PluginInputDomainAdapter aims to be transparent in use,
|
||||
* it needs to handle this timestamp adjustment itself. However,
|
||||
* some control is available over the method used for adjustment,
|
||||
* by means of the ProcessTimestampMethod setting.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to ShiftTimestamp (the
|
||||
* default), then the data passed to the wrapped plugin will be
|
||||
* calculated from the same input data block as passed to the
|
||||
* wrapper, but the timestamp passed to the plugin will be
|
||||
* advanced by half of the window size.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to ShiftData, then the
|
||||
* timestamp passed to the wrapped plugin will be the same as that
|
||||
* passed to the process call of the wrapper, but the data block
|
||||
* used to calculate the input will be shifted back (earlier) by
|
||||
* half of the window size, with half a block of zero padding at
|
||||
* the start of the first process call. This has the advantage of
|
||||
* preserving the first half block of audio without any
|
||||
* deterioration from window shaping.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to NoShift, then no adjustment
|
||||
* will be made and the timestamps will be incorrect.
|
||||
*/
|
||||
enum ProcessTimestampMethod {
|
||||
ShiftTimestamp,
|
||||
ShiftData,
|
||||
NoShift
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the method used for timestamp adjustment in plugins taking
|
||||
* frequency-domain input. See the ProcessTimestampMethod
|
||||
* documentation for details.
|
||||
*
|
||||
* This function must be called before the first call to
|
||||
* process().
|
||||
*/
|
||||
void setProcessTimestampMethod(ProcessTimestampMethod);
|
||||
|
||||
/**
|
||||
* Retrieve the method used for timestamp adjustment in plugins
|
||||
* taking frequency-domain input. See the ProcessTimestampMethod
|
||||
* documentation for details.
|
||||
*/
|
||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||
|
||||
/**
|
||||
* Return the amount by which the timestamps supplied to process()
|
||||
* are being incremented when they are passed to the plugin's own
|
||||
|
|
@ -116,9 +174,13 @@ public:
|
|||
* 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.
|
||||
* If the plugin requires time-domain input or the
|
||||
* PluginInputDomainAdapter is configured with its
|
||||
* ProcessTimestampMethod set to ShiftData instead of
|
||||
* ShiftTimestamp, then this function will return zero.
|
||||
*
|
||||
* The result of calling this function before initialise() has
|
||||
* been called is undefined.
|
||||
*/
|
||||
RealTime getTimestampAdjustment() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
@ -156,7 +156,7 @@ public:
|
|||
*/
|
||||
enum AveragingMethod {
|
||||
SampleAverage = 0,
|
||||
ContinuousTimeAverage = 1,
|
||||
ContinuousTimeAverage = 1
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
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.
|
||||
Copyright 2006-2009 Chris Cannam and QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -152,12 +152,17 @@ public:
|
|||
enum InputDomain { TimeDomain, FrequencyDomain };
|
||||
|
||||
/**
|
||||
* Get the plugin's required input domain. If this is TimeDomain,
|
||||
* the samples provided to the process() function (below) will be
|
||||
* in the time domain, as for a traditional audio processing
|
||||
* plugin. If this is FrequencyDomain, the host will carry out a
|
||||
* windowed FFT of size equal to the negotiated block size on the
|
||||
* data before passing the frequency bin data in to process().
|
||||
* Get the plugin's required input domain.
|
||||
*
|
||||
* If this is TimeDomain, the samples provided to the process()
|
||||
* function (below) will be in the time domain, as for a
|
||||
* traditional audio processing plugin.
|
||||
*
|
||||
* If this is FrequencyDomain, the host will carry out a windowed
|
||||
* FFT of size equal to the negotiated block size on the data
|
||||
* before passing the frequency bin data in to process(). The
|
||||
* input data for the FFT will be rotated so as to place the
|
||||
* origin in the centre of the block.
|
||||
* The plugin does not get to choose the window type -- the host
|
||||
* will either let the user do so, or will use a Hanning window.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define VAMP_SDK_VERSION "2.0"
|
||||
#define VAMP_SDK_VERSION "3.5"
|
||||
#define VAMP_SDK_MAJOR_VERSION 2
|
||||
#define VAMP_SDK_MINOR_VERSION 0
|
||||
#define VAMP_SDK_MINOR_VERSION 2
|
||||
|
||||
#include "plugguard.h"
|
||||
_VAMP_SDK_PLUGSPACE_BEGIN(PluginBase.h)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue