summaryrefslogtreecommitdiff
path: root/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp')
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp721
1 files changed, 0 insertions, 721 deletions
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp
deleted file mode 100644
index a14fe44086..0000000000
--- a/libs/vamp-sdk/src/vamp-hostsdk/PluginBufferingAdapter.cpp
+++ /dev/null
@@ -1,721 +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-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
- 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 <vector>
-#include <map>
-
-#include "vamp-hostsdk/PluginBufferingAdapter.h"
-#include "vamp-hostsdk/PluginInputDomainAdapter.h"
-
-using std::vector;
-using std::map;
-
-_VAMP_SDK_HOSTSPACE_BEGIN(PluginBufferingAdapter.cpp)
-
-namespace Vamp {
-
-namespace HostExt {
-
-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);
-
- FeatureSet getRemainingFeatures();
-
-protected:
- class RingBuffer
- {
- public:
- RingBuffer(int n) :
- m_buffer(new float[n+1]), m_writer(0), m_reader(0), m_size(n+1) { }
- virtual ~RingBuffer() { delete[] m_buffer; }
-
- int getSize() const { return m_size-1; }
- void reset() { m_writer = 0; m_reader = 0; }
-
- int getReadSpace() const {
- int writer = m_writer, reader = m_reader, space;
- if (writer > reader) space = writer - reader;
- else if (writer < reader) space = (writer + m_size) - reader;
- else space = 0;
- return space;
- }
-
- int getWriteSpace() const {
- int writer = m_writer;
- int reader = m_reader;
- int space = (reader + m_size - writer - 1);
- if (space >= m_size) space -= m_size;
- return space;
- }
-
- int peek(float *destination, int n) const {
-
- int available = getReadSpace();
-
- if (n > available) {
- for (int i = available; i < n; ++i) {
- destination[i] = 0.f;
- }
- n = available;
- }
- if (n == 0) return n;
-
- int reader = m_reader;
- int here = m_size - reader;
- const float *const bufbase = m_buffer + reader;
-
- if (here >= n) {
- for (int i = 0; i < n; ++i) {
- destination[i] = bufbase[i];
- }
- } else {
- for (int i = 0; i < here; ++i) {
- destination[i] = bufbase[i];
- }
- float *const destbase = destination + here;
- const int nh = n - here;
- for (int i = 0; i < nh; ++i) {
- destbase[i] = m_buffer[i];
- }
- }
-
- return n;
- }
-
- int skip(int n) {
-
- int available = getReadSpace();
- if (n > available) {
- n = available;
- }
- if (n == 0) return n;
-
- int reader = m_reader;
- reader += n;
- while (reader >= m_size) reader -= m_size;
- m_reader = reader;
- return n;
- }
-
- int write(const float *source, int n) {
-
- int available = getWriteSpace();
- if (n > available) {
- n = available;
- }
- if (n == 0) return n;
-
- int writer = m_writer;
- int here = m_size - writer;
- float *const bufbase = m_buffer + writer;
-
- if (here >= n) {
- for (int i = 0; i < n; ++i) {
- bufbase[i] = source[i];
- }
- } else {
- for (int i = 0; i < here; ++i) {
- bufbase[i] = source[i];
- }
- const int nh = n - here;
- const float *const srcbase = source + here;
- float *const buf = m_buffer;
- for (int i = 0; i < nh; ++i) {
- buf[i] = srcbase[i];
- }
- }
-
- writer += n;
- while (writer >= m_size) writer -= m_size;
- m_writer = writer;
-
- return n;
- }
-
- int zero(int n) {
-
- int available = getWriteSpace();
- if (n > available) {
- n = available;
- }
- if (n == 0) return n;
-
- int writer = m_writer;
- int here = m_size - writer;
- float *const bufbase = m_buffer + writer;
-
- if (here >= n) {
- for (int i = 0; i < n; ++i) {
- bufbase[i] = 0.f;
- }
- } else {
- for (int i = 0; i < here; ++i) {
- bufbase[i] = 0.f;
- }
- const int nh = n - here;
- for (int i = 0; i < nh; ++i) {
- m_buffer[i] = 0.f;
- }
- }
-
- writer += n;
- while (writer >= m_size) writer -= m_size;
- m_writer = writer;
-
- return n;
- }
-
- protected:
- float *m_buffer;
- int m_writer;
- int m_reader;
- int m_size;
-
- private:
- RingBuffer(const RingBuffer &); // not provided
- RingBuffer &operator=(const RingBuffer &); // not provided
- };
-
- Plugin *m_plugin;
- 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;
- long m_frame;
- bool m_unrun;
- mutable OutputList m_outputs;
- mutable std::map<int, bool> m_rewriteOutputTimes;
-
- void processBlock(FeatureSet& allFeatureSets);
-};
-
-PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
- PluginWrapper(plugin)
-{
- m_impl = new Impl(plugin, m_inputSampleRate);
-}
-
-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)
-{
- return m_impl->initialise(channels, stepSize, blockSize);
-}
-
-PluginBufferingAdapter::OutputList
-PluginBufferingAdapter::getOutputDescriptors() const
-{
- return m_impl->getOutputDescriptors();
-}
-
-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();
-}
-
-PluginBufferingAdapter::FeatureSet
-PluginBufferingAdapter::process(const float *const *inputBuffers,
- RealTime timestamp)
-{
- return m_impl->process(inputBuffers, timestamp);
-}
-
-PluginBufferingAdapter::FeatureSet
-PluginBufferingAdapter::getRemainingFeatures()
-{
- return m_impl->getRemainingFeatures();
-}
-
-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_frame(0),
- m_unrun(true)
-{
- (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes
-}
-
-PluginBufferingAdapter::Impl::~Impl()
-{
- // the adapter will delete the plugin
-
- for (size_t i = 0; i < m_channels; ++i) {
- delete m_queue[i];
- delete[] m_buffers[i];
- }
- delete[] m_buffers;
-}
-
-void
-PluginBufferingAdapter::Impl::setPluginStepSize(size_t stepSize)
-{
- 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)
-{
- if (stepSize != blockSize) {
- std::cerr << "PluginBufferingAdapter::initialise: input stepSize must be equal to blockSize for this adapter (stepSize = " << stepSize << ", blockSize = " << blockSize << ")" << std::endl;
- return false;
- }
-
- 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();
- }
-
- bool freq = (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain);
-
- // or sensible defaults if it has no preference
- if (m_blockSize == 0) {
- 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;
- }
- }
-
- // current implementation breaks if step is greater than block
- if (m_stepSize > m_blockSize) {
- 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];
-
- for (size_t i = 0; i < m_channels; ++i) {
- m_queue.push_back(new RingBuffer(m_blockSize + m_inputBlockSize));
- m_buffers[i] = new float[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
-{
- 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) {
-
- 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;
- }
- }
-
- 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_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_frame = RealTime::realTime2Frame(timestamp,
- int(m_inputSampleRate + 0.5));
- m_unrun = false;
- }
-
- // queue the new input
-
- for (size_t i = 0; i < m_channels; ++i) {
- int written = m_queue[i]->write(inputBuffers[i], m_inputBlockSize);
- if (written < int(m_inputBlockSize) && i == 0) {
- std::cerr << "WARNING: PluginBufferingAdapter::Impl::process: "
- << "Buffer overflow: wrote " << written
- << " of " << m_inputBlockSize
- << " input samples (for plugin step size "
- << m_stepSize << ", block size " << m_blockSize << ")"
- << std::endl;
- }
- }
-
- // process as much as we can
-
- while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
- processBlock(allFeatureSets);
- }
-
- return allFeatureSets;
-}
-
-PluginBufferingAdapter::FeatureSet
-PluginBufferingAdapter::Impl::getRemainingFeatures()
-{
- FeatureSet allFeatureSets;
-
- // process remaining samples in queue
- while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
- processBlock(allFeatureSets);
- }
-
- // pad any last samples remaining and process
- if (m_queue[0]->getReadSpace() > 0) {
- for (size_t i = 0; i < m_channels; ++i) {
- m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
- }
- processBlock(allFeatureSets);
- }
-
- // get remaining features
-
- FeatureSet featureSet = m_plugin->getRemainingFeatures();
-
- for (map<int, FeatureList>::iterator iter = featureSet.begin();
- iter != featureSet.end(); ++iter) {
- FeatureList featureList = iter->second;
- for (size_t i = 0; i < featureList.size(); ++i) {
- allFeatureSets[iter->first].push_back(featureList[i]);
- }
- }
-
- return allFeatureSets;
-}
-
-void
-PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
-{
- for (size_t i = 0; i < m_channels; ++i) {
- m_queue[i]->peek(m_buffers[i], m_blockSize);
- }
-
- long frame = m_frame;
- RealTime timestamp = RealTime::frame2RealTime
- (frame, int(m_inputSampleRate + 0.5));
-
- 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) {
-
- int outputNo = iter->first;
-
- if (m_rewriteOutputTimes[outputNo]) {
-
- FeatureList featureList = iter->second;
-
- for (size_t i = 0; i < featureList.size(); ++i) {
-
- switch (m_outputs[outputNo].sampleType) {
-
- case OutputDescriptor::OneSamplePerStep:
- // use our internal timestamp, always
- 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 + adjustment;
- featureList[i].hasTimestamp = true;
- }
- break;
-
- case OutputDescriptor::VariableSampleRate:
- break; // plugin must set timestamp
-
- default:
- break;
- }
-
- allFeatureSets[outputNo].push_back(featureList[i]);
- }
- } else {
- for (size_t i = 0; i < iter->second.size(); ++i) {
- allFeatureSets[outputNo].push_back(iter->second[i]);
- }
- }
- }
-
- // step forward
-
- for (size_t i = 0; i < m_channels; ++i) {
- m_queue[i]->skip(m_stepSize);
- }
-
- // increment internal frame counter each time we step forward
- m_frame += m_stepSize;
-}
-
-}
-
-}
-
-_VAMP_SDK_HOSTSPACE_END(PluginBufferingAdapter.cpp)