mirror of
https://github.com/cookiengineer/audacity
synced 2026-04-24 15:03:53 +02:00
Update libvamp to 2.5.
This commit is contained in:
@@ -62,6 +62,9 @@ whether proprietary or open-source.
|
||||
results used in the calculation, and may be a useful example of a
|
||||
plugin having several outputs with varying feature structures.
|
||||
|
||||
Plugin authors should also read the Programmer's Guide at
|
||||
http://vamp-plugins.org/guide.pdf .
|
||||
|
||||
\section hosts For Hosts
|
||||
|
||||
Hosts will normally use a Vamp::PluginHostAdapter to convert each
|
||||
|
||||
@@ -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;
|
||||
@@ -243,8 +244,10 @@ protected:
|
||||
bool m_unrun;
|
||||
mutable OutputList m_outputs;
|
||||
mutable std::map<int, bool> m_rewriteOutputTimes;
|
||||
std::map<int, int> m_fixedRateFeatureNos; // output no -> feature no
|
||||
|
||||
void processBlock(FeatureSet& allFeatureSets);
|
||||
void adjustFixedRateFeatureTime(int outputNo, Feature &);
|
||||
};
|
||||
|
||||
PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
|
||||
@@ -468,8 +471,8 @@ PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_
|
||||
m_blockSize = newBlockSize;
|
||||
}
|
||||
|
||||
std::cerr << "PluginBufferingAdapter::initialise: NOTE: stepSize " << m_inputStepSize << " -> " << m_stepSize
|
||||
<< ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
|
||||
// std::cerr << "PluginBufferingAdapter::initialise: NOTE: stepSize " << m_inputStepSize << " -> " << m_stepSize
|
||||
// << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
|
||||
|
||||
m_buffers = new float *[m_channels];
|
||||
|
||||
@@ -606,6 +609,25 @@ PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
|
||||
return allFeatureSets;
|
||||
}
|
||||
|
||||
void
|
||||
PluginBufferingAdapter::Impl::adjustFixedRateFeatureTime(int outputNo,
|
||||
Feature &feature)
|
||||
{
|
||||
if (feature.hasTimestamp) {
|
||||
double secs = feature.timestamp.sec;
|
||||
secs += feature.timestamp.nsec / 1e9;
|
||||
m_fixedRateFeatureNos[outputNo] =
|
||||
int(secs * double(m_outputs[outputNo].sampleRate) + 0.5);
|
||||
}
|
||||
|
||||
feature.timestamp = RealTime::fromSeconds
|
||||
(m_fixedRateFeatureNos[outputNo] / double(m_outputs[outputNo].sampleRate));
|
||||
|
||||
feature.hasTimestamp = true;
|
||||
|
||||
m_fixedRateFeatureNos[outputNo] = m_fixedRateFeatureNos[outputNo] + 1;
|
||||
}
|
||||
|
||||
PluginBufferingAdapter::FeatureSet
|
||||
PluginBufferingAdapter::Impl::getRemainingFeatures()
|
||||
{
|
||||
@@ -630,9 +652,18 @@ PluginBufferingAdapter::Impl::getRemainingFeatures()
|
||||
|
||||
for (map<int, FeatureList>::iterator iter = featureSet.begin();
|
||||
iter != featureSet.end(); ++iter) {
|
||||
|
||||
int outputNo = iter->first;
|
||||
FeatureList featureList = iter->second;
|
||||
|
||||
for (size_t i = 0; i < featureList.size(); ++i) {
|
||||
allFeatureSets[iter->first].push_back(featureList[i]);
|
||||
|
||||
if (m_outputs[outputNo].sampleType ==
|
||||
OutputDescriptor::FixedSampleRate) {
|
||||
adjustFixedRateFeatureTime(outputNo, featureList[i]);
|
||||
}
|
||||
|
||||
allFeatureSets[outputNo].push_back(featureList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,6 +683,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,20 +706,17 @@ 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].hasTimestamp = true;
|
||||
}
|
||||
adjustFixedRateFeatureTime(outputNo, featureList[i]);
|
||||
break;
|
||||
|
||||
case OutputDescriptor::VariableSampleRate:
|
||||
break; // plugin must set timestamp
|
||||
// plugin must set timestamp
|
||||
break;
|
||||
|
||||
default:
|
||||
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
|
||||
@@ -163,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) {
|
||||
|
||||
@@ -175,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 != 5 )
|
||||
#error Unexpected version of Vamp SDK header included
|
||||
#endif
|
||||
|
||||
_VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
|
||||
@@ -265,7 +265,11 @@ PluginHostAdapter::getCurrentProgram() const
|
||||
if (!m_handle) return "";
|
||||
|
||||
int pn = m_descriptor->getCurrentProgram(m_handle);
|
||||
return m_descriptor->programs[pn];
|
||||
if (pn < (int)m_descriptor->programCount) {
|
||||
return m_descriptor->programs[pn];
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
This file is based in part on Don Cross's public domain FFT
|
||||
implementation.
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
|
||||
/**
|
||||
* If you want to compile using FFTW instead of the built-in FFT
|
||||
@@ -67,6 +69,9 @@
|
||||
*/
|
||||
#ifdef HAVE_FFTW3
|
||||
#include <fftw3.h>
|
||||
#warning "Compiling with FFTW3 support will result in a GPL binary"
|
||||
#else
|
||||
#include "../vamp-sdk/FFTimpl.cpp"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -83,23 +88,37 @@ 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;
|
||||
|
||||
WindowType getWindowType() const;
|
||||
void setWindowType(WindowType type);
|
||||
|
||||
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;
|
||||
|
||||
WindowType m_windowType;
|
||||
Window<double> *m_window;
|
||||
|
||||
ProcessTimestampMethod m_method;
|
||||
int m_processCount;
|
||||
float **m_shiftBuffers;
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_plan m_plan;
|
||||
@@ -107,11 +126,14 @@ protected:
|
||||
#else
|
||||
double *m_ro;
|
||||
double *m_io;
|
||||
void fft(unsigned int n, bool inverse,
|
||||
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;
|
||||
|
||||
Window<double>::WindowType convertType(WindowType t) const;
|
||||
};
|
||||
|
||||
PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
|
||||
@@ -131,6 +153,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,21 +183,50 @@ 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
|
||||
{
|
||||
return m_impl->getTimestampAdjustment();
|
||||
}
|
||||
|
||||
PluginInputDomainAdapter::WindowType
|
||||
PluginInputDomainAdapter::getWindowType() const
|
||||
{
|
||||
return m_impl->getWindowType();
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::setWindowType(WindowType w)
|
||||
{
|
||||
m_impl->setWindowType(w);
|
||||
}
|
||||
|
||||
|
||||
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_windowType(HanningWindow),
|
||||
m_window(0),
|
||||
m_method(ShiftTimestamp),
|
||||
m_processCount(0),
|
||||
m_shiftBuffers(0),
|
||||
#ifdef HAVE_FFTW3
|
||||
m_plan(0),
|
||||
m_cbuf(0)
|
||||
@@ -184,6 +241,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];
|
||||
@@ -201,7 +265,8 @@ PluginInputDomainAdapter::Impl::~Impl()
|
||||
delete[] m_ro;
|
||||
delete[] m_io;
|
||||
#endif
|
||||
delete[] m_window;
|
||||
|
||||
delete m_window;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +280,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 +288,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;
|
||||
}
|
||||
|
||||
@@ -248,9 +314,10 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
||||
delete[] m_ro;
|
||||
delete[] m_io;
|
||||
#endif
|
||||
delete[] m_window;
|
||||
delete m_window;
|
||||
}
|
||||
|
||||
m_stepSize = int(stepSize);
|
||||
m_blockSize = int(blockSize);
|
||||
m_channels = int(channels);
|
||||
|
||||
@@ -258,12 +325,8 @@ PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, siz
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
m_freqbuf[c] = new float[m_blockSize + 2];
|
||||
}
|
||||
m_window = new double[m_blockSize];
|
||||
|
||||
for (int i = 0; i < m_blockSize; ++i) {
|
||||
// Hanning window
|
||||
m_window[i] = (0.50 - 0.50 * cos((2.0 * M_PI * i) / m_blockSize));
|
||||
}
|
||||
m_window = new Window<double>(convertType(m_windowType), m_blockSize);
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
m_ri = (double *)fftw_malloc(blockSize * sizeof(double));
|
||||
@@ -275,9 +338,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 +383,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 +412,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 +426,66 @@ 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;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
|
||||
{
|
||||
if (m_windowType == t) return;
|
||||
m_windowType = t;
|
||||
if (m_window) {
|
||||
delete m_window;
|
||||
m_window = new Window<double>(convertType(m_windowType), m_blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
PluginInputDomainAdapter::WindowType
|
||||
PluginInputDomainAdapter::Impl::getWindowType() const
|
||||
{
|
||||
return m_windowType;
|
||||
}
|
||||
|
||||
Window<double>::WindowType
|
||||
PluginInputDomainAdapter::Impl::convertType(WindowType t) const
|
||||
{
|
||||
switch (t) {
|
||||
case RectangularWindow:
|
||||
return Window<double>::RectangularWindow;
|
||||
case BartlettWindow:
|
||||
return Window<double>::BartlettWindow;
|
||||
case HammingWindow:
|
||||
return Window<double>::HammingWindow;
|
||||
case HanningWindow:
|
||||
return Window<double>::HanningWindow;
|
||||
case BlackmanWindow:
|
||||
return Window<double>::BlackmanWindow;
|
||||
case NuttallWindow:
|
||||
return Window<double>::NuttallWindow;
|
||||
case BlackmanHarrisWindow:
|
||||
return Window<double>::BlackmanHarrisWindow;
|
||||
default:
|
||||
return Window<double>::HanningWindow;
|
||||
}
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
@@ -368,59 +494,24 @@ 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.
|
||||
if (m_method == ShiftTimestamp || m_method == NoShift) {
|
||||
return processShiftingTimestamp(inputBuffers, timestamp);
|
||||
} else {
|
||||
return processShiftingData(inputBuffers, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
|
||||
|
||||
timestamp = timestamp + getTimestampAdjustment();
|
||||
|
||||
// std::cerr << " to " << timestamp << std::endl;
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
{
|
||||
if (m_method == ShiftTimestamp) {
|
||||
timestamp = timestamp + getTimestampAdjustment();
|
||||
}
|
||||
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
|
||||
for (int i = 0; i < m_blockSize; ++i) {
|
||||
m_ri[i] = double(inputBuffers[c][i]) * m_window[i];
|
||||
}
|
||||
m_window->cut(inputBuffers[c], m_ri);
|
||||
|
||||
for (int i = 0; i < m_blockSize/2; ++i) {
|
||||
// FFT shift
|
||||
@@ -430,148 +521,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);
|
||||
}
|
||||
|
||||
#ifndef HAVE_FFTW3
|
||||
|
||||
void
|
||||
PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse,
|
||||
double *ri, double *ii, double *ro, double *io)
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
{
|
||||
if (!ri || !ro || !io) return;
|
||||
|
||||
unsigned int bits;
|
||||
unsigned int i, j, k, m;
|
||||
unsigned int blockSize, blockEnd;
|
||||
|
||||
double tr, ti;
|
||||
|
||||
if (n < 2) return;
|
||||
if (n & (n-1)) return;
|
||||
|
||||
double angle = 2.0 * M_PI;
|
||||
if (inverse) angle = -angle;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
if (n & (1 << i)) {
|
||||
bits = i;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int tableSize = 0;
|
||||
static int *table = 0;
|
||||
|
||||
if (tableSize != n) {
|
||||
|
||||
delete[] table;
|
||||
|
||||
table = new int[n];
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
||||
m = i;
|
||||
|
||||
for (j = k = 0; j < bits; ++j) {
|
||||
k = (k << 1) | (m & 1);
|
||||
m >>= 1;
|
||||
}
|
||||
|
||||
table[i] = k;
|
||||
}
|
||||
|
||||
tableSize = n;
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
if (ii) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
ro[table[i]] = ri[i];
|
||||
io[table[i]] = ii[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < n; ++i) {
|
||||
ro[table[i]] = ri[i];
|
||||
io[table[i]] = 0.0;
|
||||
}
|
||||
for (int c = 0; c < m_channels; ++c) {
|
||||
|
||||
m_window->cut(m_shiftBuffers[c], m_ri);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
blockEnd = 1;
|
||||
++m_processCount;
|
||||
|
||||
for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
|
||||
|
||||
double delta = angle / (double)blockSize;
|
||||
double sm2 = -sin(-2 * delta);
|
||||
double sm1 = -sin(-delta);
|
||||
double cm2 = cos(-2 * delta);
|
||||
double cm1 = cos(-delta);
|
||||
double w = 2 * cm1;
|
||||
double ar[3], ai[3];
|
||||
|
||||
for (i = 0; i < n; i += blockSize) {
|
||||
|
||||
ar[2] = cm2;
|
||||
ar[1] = cm1;
|
||||
|
||||
ai[2] = sm2;
|
||||
ai[1] = sm1;
|
||||
|
||||
for (j = i, m = 0; m < blockEnd; j++, m++) {
|
||||
|
||||
ar[0] = w * ar[1] - ar[2];
|
||||
ar[2] = ar[1];
|
||||
ar[1] = ar[0];
|
||||
|
||||
ai[0] = w * ai[1] - ai[2];
|
||||
ai[2] = ai[1];
|
||||
ai[1] = ai[0];
|
||||
|
||||
k = j + blockEnd;
|
||||
tr = ar[0] * ro[k] - ai[0] * io[k];
|
||||
ti = ar[0] * io[k] + ai[0] * ro[k];
|
||||
|
||||
ro[k] = ro[j] - tr;
|
||||
io[k] = io[j] - ti;
|
||||
|
||||
ro[j] += tr;
|
||||
io[j] += ti;
|
||||
}
|
||||
}
|
||||
|
||||
blockEnd = blockSize;
|
||||
}
|
||||
|
||||
if (inverse) {
|
||||
|
||||
double denom = (double)n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
ro[i] /= denom;
|
||||
io[i] /= denom;
|
||||
}
|
||||
}
|
||||
return m_plugin->process(m_freqbuf, timestamp);
|
||||
}
|
||||
|
||||
#ifndef HAVE_FFTW3
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -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,18 +270,24 @@ 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) ==
|
||||
@@ -289,6 +295,12 @@ PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
|
||||
m_pluginLibraryNameMap[key] = fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && forPlugin != "") {
|
||||
cerr << "Vamp::HostExt::PluginLoader: Plugin \""
|
||||
<< identifier << "\" not found in library \""
|
||||
<< fullPath << "\"" << endl;
|
||||
}
|
||||
|
||||
unloadLibrary(handle);
|
||||
}
|
||||
@@ -365,7 +377,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 +390,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 +530,21 @@ PluginLoader::Impl::loadLibrary(string path)
|
||||
{
|
||||
void *handle = 0;
|
||||
#ifdef _WIN32
|
||||
#ifdef UNICODE
|
||||
int len = path.length() + 1; // 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 +595,41 @@ PluginLoader::Impl::listFiles(string dir, string extension)
|
||||
vector<string> files;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
string expression = dir + "\\*." + extension;
|
||||
#ifdef UNICODE
|
||||
int len = expression.length() + 1; // 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) + 1;
|
||||
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 +641,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
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
void reset();
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
@@ -167,6 +169,12 @@ PluginSummarisingAdapter::initialise(size_t channels,
|
||||
m_impl->initialise(channels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::reset()
|
||||
{
|
||||
m_impl->reset();
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
|
||||
{
|
||||
@@ -220,6 +228,19 @@ PluginSummarisingAdapter::Impl::initialise(size_t channels,
|
||||
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)
|
||||
@@ -545,8 +566,6 @@ PluginSummarisingAdapter::Impl::accumulateFinalDurations()
|
||||
|
||||
if (acount == 0) continue;
|
||||
|
||||
RealTime prevTimestamp = i->second;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
std::cerr << "output " << output << ": ";
|
||||
#endif
|
||||
@@ -611,8 +630,11 @@ 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) {
|
||||
|
||||
@@ -645,9 +667,24 @@ PluginSummarisingAdapter::Impl::segment()
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
167
lib-src/libvamp/src/vamp-hostsdk/Window.h
Normal file
167
lib-src/libvamp/src/vamp-hostsdk/Window.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*- 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-2011 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 _WINDOW_H_
|
||||
#define _WINDOW_H_
|
||||
|
||||
#include <vamp-hostsdk/hostguard.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
_VAMP_SDK_HOSTSPACE_BEGIN(Window.h)
|
||||
|
||||
template <typename T>
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
enum WindowType {
|
||||
RectangularWindow,
|
||||
BartlettWindow,
|
||||
HammingWindow,
|
||||
HanningWindow,
|
||||
BlackmanWindow,
|
||||
NuttallWindow,
|
||||
BlackmanHarrisWindow
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a windower of the given type.
|
||||
*/
|
||||
Window(WindowType type, size_t size) : m_type(type), m_size(size) { encache(); }
|
||||
Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); }
|
||||
Window &operator=(const Window &w) {
|
||||
if (&w == this) return *this;
|
||||
m_type = w.m_type;
|
||||
m_size = w.m_size;
|
||||
encache();
|
||||
return *this;
|
||||
}
|
||||
virtual ~Window() { delete[] m_cache; }
|
||||
|
||||
void cut(T *src) const { cut(src, src); }
|
||||
void cut(T *src, T *dst) const {
|
||||
for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
|
||||
}
|
||||
template <typename T0>
|
||||
void cut(T0 *src, T *dst) const {
|
||||
for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
|
||||
}
|
||||
|
||||
T getArea() { return m_area; }
|
||||
T getValue(size_t i) { return m_cache[i]; }
|
||||
|
||||
WindowType getType() const { return m_type; }
|
||||
size_t getSize() const { return m_size; }
|
||||
|
||||
protected:
|
||||
WindowType m_type;
|
||||
size_t m_size;
|
||||
T *m_cache;
|
||||
T m_area;
|
||||
|
||||
void encache();
|
||||
void cosinewin(T *, T, T, T, T);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void Window<T>::encache()
|
||||
{
|
||||
int n = int(m_size);
|
||||
T *mult = new T[n];
|
||||
int i;
|
||||
for (i = 0; i < n; ++i) mult[i] = 1.0;
|
||||
|
||||
switch (m_type) {
|
||||
|
||||
case RectangularWindow:
|
||||
for (i = 0; i < n; ++i) {
|
||||
mult[i] *= 0.5;
|
||||
}
|
||||
break;
|
||||
|
||||
case BartlettWindow:
|
||||
for (i = 0; i < n/2; ++i) {
|
||||
mult[i] *= (i / T(n/2));
|
||||
mult[i + n/2] *= (1.0 - (i / T(n/2)));
|
||||
}
|
||||
break;
|
||||
|
||||
case HammingWindow:
|
||||
cosinewin(mult, 0.54, 0.46, 0.0, 0.0);
|
||||
break;
|
||||
|
||||
case HanningWindow:
|
||||
cosinewin(mult, 0.50, 0.50, 0.0, 0.0);
|
||||
break;
|
||||
|
||||
case BlackmanWindow:
|
||||
cosinewin(mult, 0.42, 0.50, 0.08, 0.0);
|
||||
break;
|
||||
|
||||
case NuttallWindow:
|
||||
cosinewin(mult, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
|
||||
break;
|
||||
|
||||
case BlackmanHarrisWindow:
|
||||
cosinewin(mult, 0.35875, 0.48829, 0.14128, 0.01168);
|
||||
break;
|
||||
}
|
||||
|
||||
m_cache = mult;
|
||||
|
||||
m_area = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
m_area += m_cache[i];
|
||||
}
|
||||
m_area /= n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Window<T>::cosinewin(T *mult, T a0, T a1, T a2, T a3)
|
||||
{
|
||||
int n = int(m_size);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
mult[i] *= (a0
|
||||
- a1 * cos((2 * M_PI * i) / n)
|
||||
+ a2 * cos((4 * M_PI * i) / n)
|
||||
- a3 * cos((6 * M_PI * i) / n));
|
||||
}
|
||||
}
|
||||
|
||||
_VAMP_SDK_HOSTSPACE_END(Window.h)
|
||||
|
||||
#endif
|
||||
11
lib-src/libvamp/src/vamp-hostsdk/acsymbols.c
Normal file
11
lib-src/libvamp/src/vamp-hostsdk/acsymbols.c
Normal file
@@ -0,0 +1,11 @@
|
||||
/* These stubs are provided so that autoconf can check library
|
||||
* versions using C symbols only */
|
||||
|
||||
extern void libvamphostsdk_v_2_5_present(void) { }
|
||||
extern void libvamphostsdk_v_2_4_present(void) { }
|
||||
extern void libvamphostsdk_v_2_3_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_3_present(void) { }
|
||||
extern void libvamphostsdk_v_2_2_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_2_present(void) { }
|
||||
extern void libvamphostsdk_v_2_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_0_present(void) { }
|
||||
75
lib-src/libvamp/src/vamp-sdk/FFT.cpp
Normal file
75
lib-src/libvamp/src/vamp-sdk/FFT.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* -*- 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-2012 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-sdk/FFT.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 5 )
|
||||
#error Unexpected version of Vamp SDK header included
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
_VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp)
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
#include "FFTimpl.cpp"
|
||||
|
||||
void
|
||||
FFT::forward(unsigned int n,
|
||||
const double *ri, const double *ii,
|
||||
double *ro, double *io)
|
||||
{
|
||||
fft(n, false, ri, ii, ro, io);
|
||||
}
|
||||
|
||||
void
|
||||
FFT::inverse(unsigned int n,
|
||||
const double *ri, const double *ii,
|
||||
double *ro, double *io)
|
||||
{
|
||||
fft(n, true, ri, ii, ro, io);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_VAMP_SDK_PLUGSPACE_END(FFT.cpp)
|
||||
|
||||
116
lib-src/libvamp/src/vamp-sdk/FFTimpl.cpp
Normal file
116
lib-src/libvamp/src/vamp-sdk/FFTimpl.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
/* Public domain FFT implementation from Don Cross. */
|
||||
|
||||
static void
|
||||
fft(unsigned int n, bool inverse,
|
||||
const double *ri, const double *ii,
|
||||
double *ro, double *io)
|
||||
{
|
||||
if (!ri || !ro || !io) return;
|
||||
|
||||
unsigned int bits;
|
||||
unsigned int i, j, k, m;
|
||||
unsigned int blockSize, blockEnd;
|
||||
|
||||
double tr, ti;
|
||||
|
||||
if (n < 2) return;
|
||||
if (n & (n-1)) return;
|
||||
|
||||
double angle = 2.0 * M_PI;
|
||||
if (inverse) angle = -angle;
|
||||
|
||||
for (i = 0; ; ++i) {
|
||||
if (n & (1 << i)) {
|
||||
bits = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int *table = (int *)_malloca(n * sizeof(int));
|
||||
#else
|
||||
int table[n];
|
||||
#endif
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
m = i;
|
||||
for (j = k = 0; j < bits; ++j) {
|
||||
k = (k << 1) | (m & 1);
|
||||
m >>= 1;
|
||||
}
|
||||
table[i] = k;
|
||||
}
|
||||
|
||||
if (ii) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
ro[table[i]] = ri[i];
|
||||
io[table[i]] = ii[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < n; ++i) {
|
||||
ro[table[i]] = ri[i];
|
||||
io[table[i]] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
blockEnd = 1;
|
||||
|
||||
for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
|
||||
|
||||
double delta = angle / (double)blockSize;
|
||||
double sm2 = -sin(-2 * delta);
|
||||
double sm1 = -sin(-delta);
|
||||
double cm2 = cos(-2 * delta);
|
||||
double cm1 = cos(-delta);
|
||||
double w = 2 * cm1;
|
||||
double ar[3], ai[3];
|
||||
|
||||
for (i = 0; i < n; i += blockSize) {
|
||||
|
||||
ar[2] = cm2;
|
||||
ar[1] = cm1;
|
||||
|
||||
ai[2] = sm2;
|
||||
ai[1] = sm1;
|
||||
|
||||
for (j = i, m = 0; m < blockEnd; j++, m++) {
|
||||
|
||||
ar[0] = w * ar[1] - ar[2];
|
||||
ar[2] = ar[1];
|
||||
ar[1] = ar[0];
|
||||
|
||||
ai[0] = w * ai[1] - ai[2];
|
||||
ai[2] = ai[1];
|
||||
ai[1] = ai[0];
|
||||
|
||||
k = j + blockEnd;
|
||||
tr = ar[0] * ro[k] - ai[0] * io[k];
|
||||
ti = ar[0] * io[k] + ai[0] * ro[k];
|
||||
|
||||
ro[k] = ro[j] - tr;
|
||||
io[k] = io[j] - ti;
|
||||
|
||||
ro[j] += tr;
|
||||
io[j] += ti;
|
||||
}
|
||||
}
|
||||
|
||||
blockEnd = blockSize;
|
||||
}
|
||||
|
||||
if (inverse) {
|
||||
|
||||
double denom = (double)n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
ro[i] /= denom;
|
||||
io[i] /= denom;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_freea(table);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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 != 5 )
|
||||
#error Unexpected version of Vamp SDK header included
|
||||
#endif
|
||||
|
||||
|
||||
@@ -168,6 +168,11 @@ PluginAdapterBase::Impl::getDescriptor()
|
||||
if (m_populated) return &m_descriptor;
|
||||
|
||||
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: "
|
||||
|
||||
11
lib-src/libvamp/src/vamp-sdk/acsymbols.c
Normal file
11
lib-src/libvamp/src/vamp-sdk/acsymbols.c
Normal file
@@ -0,0 +1,11 @@
|
||||
/* These stubs are provided so that autoconf can check library
|
||||
* versions using C symbols only */
|
||||
|
||||
extern void libvampsdk_v_2_5_present(void) { }
|
||||
extern void libvampsdk_v_2_4_present(void) { }
|
||||
extern void libvampsdk_v_2_3_1_present(void) { }
|
||||
extern void libvampsdk_v_2_3_present(void) { }
|
||||
extern void libvampsdk_v_2_2_1_present(void) { }
|
||||
extern void libvampsdk_v_2_2_present(void) { }
|
||||
extern void libvampsdk_v_2_1_present(void) { }
|
||||
extern void libvampsdk_v_2_0_present(void) { }
|
||||
Reference in New Issue
Block a user