# HG changeset patch # User cannam # Date 1143814911 0 # Node ID 6479539d1b32056cb2477596121ab072e31e5b42 * Importing first cut of Sonic Visualiser's Vamp plugin format SDK diff -r 000000000000 -r 6479539d1b32 COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,28 @@ + + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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. + diff -r 000000000000 -r 6479539d1b32 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,12 @@ + + +all: + $(MAKE) -C examples all + +clean: + $(MAKE) -C examples clean + +distclean: + $(MAKE) -C examples distclean + rm -f *~ *.bak $(TARGET) + diff -r 000000000000 -r 6479539d1b32 examples/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/Makefile Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,24 @@ + +TARGET := plugins.so +OBJECTS := ZeroCrossing.o SpectralCentroid.o plugins.o + +SDKPATH := ../sdk +APIPATH := ../vamp + +CXXFLAGS := $(CXXFLAGS) -O2 -Wall -I$(SDKPATH) -I$(APIPATH) + +LDFLAGS := -shared -Wl,-Bsymbolic + +APIFILES := $(SDKPATH)/PluginAdapter.cpp $(SDKPATH)/RealTime.cpp + +plugins.so: $(OBJECTS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(TARGET) $(APIFILES) $(OBJECTS) + +all: $(TARGET) + +clean: + rm -f $(OBJECTS) + +distclean: clean + rm -f *~ *.bak $(TARGET) + diff -r 000000000000 -r 6479539d1b32 examples/SpectralCentroid.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/SpectralCentroid.cpp Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,211 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 "SpectralCentroid.h" + +/* +#include "dsp/transforms/FFT.h" +#include "base/Window.h" +*/ + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + + +SpectralCentroid::SpectralCentroid(float inputSampleRate) : + Plugin(inputSampleRate), + m_stepSize(0), + m_blockSize(0), + m_workBuffer(0) +{ +} + +SpectralCentroid::~SpectralCentroid() +{ + delete m_workBuffer; +} + +string +SpectralCentroid::getName() const +{ + return "spectralcentroid"; +} + +string +SpectralCentroid::getDescription() const +{ + return "Spectral Centroid"; +} + +string +SpectralCentroid::getMaker() const +{ + return "QMUL"; +} + +int +SpectralCentroid::getPluginVersion() const +{ + return 2; +} + +string +SpectralCentroid::getCopyright() const +{ + return "GPL"; +} + +bool +SpectralCentroid::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + m_stepSize = stepSize; + m_blockSize = blockSize; + + delete m_workBuffer; + m_workBuffer = new double[m_blockSize * 4]; + + return true; +} + +void +SpectralCentroid::reset() +{ + delete m_workBuffer; + m_workBuffer = new double[m_blockSize * 4]; +} + +size_t +SpectralCentroid::getPreferredStepSize() const +{ + return 2048; // or whatever -- parameter? +} + +size_t +SpectralCentroid::getPreferredBlockSize() const +{ + return getPreferredStepSize(); +} + +SpectralCentroid::OutputList +SpectralCentroid::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.name = "logcentroid"; + d.unit = "Hz"; + d.description = "Log Frequency Centroid"; + d.hasFixedValueCount = true; + d.valueCount = 1; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(d); + + d.name = "linearcentroid"; + d.description = "Linear Frequency Centroid"; + list.push_back(d); + + return list; +} + +SpectralCentroid::FeatureSet +SpectralCentroid::process(float **inputBuffers, Vamp::RealTime) +{ + if (m_stepSize == 0) { + cerr << "ERROR: SpectralCentroid::process: " + << "SpectralCentroid has not been initialised" + << endl; + return FeatureSet(); + } + +/* + for (size_t i = 0; i < m_blockSize; ++i) { + m_workBuffer[i] = inputBuffers[0][i]; + m_workBuffer[i + m_blockSize] = 0.0; + } + + Window(HanningWindow, m_blockSize).cut(m_workBuffer); + + FFT::process(m_blockSize, false, + m_workBuffer, + m_workBuffer + m_blockSize, + m_workBuffer + m_blockSize*2, + m_workBuffer + m_blockSize*3); +*/ + + double numLin = 0.0, numLog = 0.0, denom = 0.0; + + for (size_t i = 1; i < m_blockSize/2; ++i) { + double freq = (double(i) * m_inputSampleRate) / m_blockSize; + double real = inputBuffers[0][i*2]; + double imag = inputBuffers[0][i*2 + 1]; + double power = sqrt(real * real + imag * imag) / (m_blockSize/2); + numLin += freq * power; + numLog += log10f(freq) * power; + denom += power; + } + + FeatureSet returnFeatures; + + std::cerr << "power " << denom << ", block size " << m_blockSize << std::endl; + + if (denom != 0.0) { + float centroidLin = float(numLin / denom); + float centroidLog = exp10f(float(numLog / denom)); + Feature feature; + feature.hasTimestamp = false; + feature.values.push_back(centroidLog); + returnFeatures[0].push_back(feature); + feature.values.clear(); + feature.values.push_back(centroidLin); + returnFeatures[1].push_back(feature); + } + + return returnFeatures; +} + +SpectralCentroid::FeatureSet +SpectralCentroid::getRemainingFeatures() +{ + return FeatureSet(); +} + diff -r 000000000000 -r 6479539d1b32 examples/SpectralCentroid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/SpectralCentroid.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,77 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 _SPECTRAL_CENTROID_PLUGIN_H_ +#define _SPECTRAL_CENTROID_PLUGIN_H_ + +#include "Plugin.h" + +class SpectralCentroidData; + +class SpectralCentroid : public Vamp::Plugin +{ +public: + SpectralCentroid(float inputSampleRate); + virtual ~SpectralCentroid(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return FrequencyDomain; } + + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(float **inputBuffers, Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + size_t m_stepSize; + size_t m_blockSize; + double *m_workBuffer; +}; + + +#endif diff -r 000000000000 -r 6479539d1b32 examples/ZeroCrossing.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/ZeroCrossing.cpp Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,197 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 "ZeroCrossing.h" + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + + +ZeroCrossing::ZeroCrossing(float inputSampleRate) : + Plugin(inputSampleRate), + m_stepSize(0), + m_previousSample(0.0f) +{ +} + +ZeroCrossing::~ZeroCrossing() +{ +} + +string +ZeroCrossing::getName() const +{ + return "zerocrossing"; +} + +string +ZeroCrossing::getDescription() const +{ + return "Zero Crossings"; +} + +string +ZeroCrossing::getMaker() const +{ + return "QMUL"; +} + +int +ZeroCrossing::getPluginVersion() const +{ + return 2; +} + +string +ZeroCrossing::getCopyright() const +{ + return "GPL"; +} + +bool +ZeroCrossing::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + m_stepSize = std::min(stepSize, blockSize); + + return true; +} + +void +ZeroCrossing::reset() +{ + m_previousSample = 0.0f; +} + +size_t +ZeroCrossing::getPreferredStepSize() const +{ + return 4096; // or whatever +} + +size_t +ZeroCrossing::getPreferredBlockSize() const +{ + return getPreferredStepSize(); +} + +ZeroCrossing::OutputList +ZeroCrossing::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor zc; + zc.name = "counts"; + zc.unit = "crossings"; + zc.description = "Zero Crossing Counts"; + zc.hasFixedValueCount = true; + zc.valueCount = 1; + zc.hasKnownExtents = false; + zc.isQuantized = true; + zc.quantizeStep = 1.0; + zc.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(zc); + + zc.name = "zerocrossings"; + zc.unit = ""; + zc.description = "Zero Crossings"; + zc.hasFixedValueCount = true; + zc.valueCount = 0; + zc.sampleType = OutputDescriptor::VariableSampleRate; + zc.sampleRate = m_inputSampleRate; + list.push_back(zc); + + return list; +} + +ZeroCrossing::FeatureSet +ZeroCrossing::process(float **inputBuffers, Vamp::RealTime timestamp) +{ + if (m_stepSize == 0) { + cerr << "ERROR: ZeroCrossing::process: " + << "ZeroCrossing has not been initialised" + << endl; + return FeatureSet(); + } + + float prev = m_previousSample; + size_t count = 0; + + FeatureSet returnFeatures; + + for (size_t i = 0; i < m_stepSize; ++i) { + + float sample = inputBuffers[0][i]; + bool crossing = false; + + if (sample <= 0.0) { + if (prev > 0.0) crossing = true; + } else if (sample > 0.0) { + if (prev <= 0.0) crossing = true; + } + + if (crossing) { + ++count; + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = timestamp + + Vamp::RealTime::frame2RealTime(i, (size_t)m_inputSampleRate); + returnFeatures[1].push_back(feature); + } + + prev = sample; + } + + m_previousSample = prev; + + Feature feature; + feature.hasTimestamp = false; + feature.values.push_back(count); + + returnFeatures[0].push_back(feature); + return returnFeatures; +} + +ZeroCrossing::FeatureSet +ZeroCrossing::getRemainingFeatures() +{ + return FeatureSet(); +} + diff -r 000000000000 -r 6479539d1b32 examples/ZeroCrossing.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/ZeroCrossing.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,76 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 _ZERO_CROSSING_PLUGIN_H_ +#define _ZERO_CROSSING_PLUGIN_H_ + +#include "Plugin.h" + +class ZeroCrossingData; + +class ZeroCrossing : public Vamp::Plugin +{ +public: + ZeroCrossing(float inputSampleRate); + virtual ~ZeroCrossing(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(float **inputBuffers, Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + size_t m_stepSize; + float m_previousSample; +}; + + +#endif diff -r 000000000000 -r 6479539d1b32 examples/plugins.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/plugins.cpp Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,54 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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.h" + +#include "PluginAdapter.h" +#include "ZeroCrossing.h" +#include "SpectralCentroid.h" + +static Vamp::PluginAdapter zeroCrossingAdapter; +static Vamp::PluginAdapter spectralCentroidAdapter; + +const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int index) +{ + switch (index) { + case 0: return zeroCrossingAdapter.getDescriptor(); + case 1: return spectralCentroidAdapter.getDescriptor(); + default: return 0; + } +} + diff -r 000000000000 -r 6479539d1b32 sdk/Plugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/Plugin.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,369 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef _VAMP_PLUGIN_H_ +#define _VAMP_PLUGIN_H_ + +#include "PluginBase.h" +#include "RealTime.h" + +#include +#include +#include + +namespace Vamp { + +/** + * Vamp::Plugin is a base class for plugin instance classes + * that provide feature extraction from audio or related data. + * + * In most cases, the input will be audio and the output will be a + * stream of derived data at a lower sampling resolution than the + * input. + * + * Note that this class inherits several abstract methods from + * PluginBase, that must be implemented by the subclass. + */ + +/** + * Plugin Lifecycle + * ================ + * + * Feature extraction plugins are managed differently from real-time + * plugins (such as VST effects). The main difference is that the + * parameters for a feature extraction plugin are configured before + * the plugin is used, and do not change during use. + * + * 1. Host constructs the plugin, passing it the input sample rate. + * The plugin may do basic initialisation, but should not do anything + * computationally expensive at this point. + * + * 2. Host may query the plugin's available outputs. + * + * 3. Host queries programs and parameter descriptors, and may set + * some or all of them. Parameters that are not explicitly set should + * take their default values as specified in the parameter descriptor. + * When a program is set, the parameter values may change and the host + * will re-query them to check. + * + * 4. Host queries the preferred step size, block size, number of + * channels, and the number of values per feature for the plugin's + * outputs. These may all vary depending on the parameter values. + * (Note however that you cannot make the number of distinct outputs + * dependent on parameter values; nor can you make any of these depend + * on the number of input channels.) + * + * 5. Plugin is properly initialised with a call to initialise. This + * fixes the step size, block size, and number of channels, as well as + * all of the parameter and program settings. If the values passed in + * to initialise do not match the plugin's advertised preferred values + * from step 4, the plugin may refuse to initialise and return false + * (although if possible it should accept the new values). + * + * 6. Host will repeatedly call the process method to pass in blocks + * of input data. This method may return features extracted from that + * data (if the plugin is causal). + * + * 7. Host will call getRemainingFeatures exactly once, after all the + * input data has been processed. This may return any non-causal or + * leftover features. + * + * 8. At any point after initialise was called, the host may + * optionally call the reset method and restart processing. (This + * does not mean it can change the parameters, which are fixed from + * initialise until destruction.) + * + * A plugin does not need to handle the case where setParameter or + * selectProgram is called after initialise has been called. It's the + * host's responsibility not to do that. + */ + +class Plugin : public PluginBase +{ +public: + /** + * Initialise a plugin to prepare it for use with the given number + * of input channels, step size (window increment, in sample + * frames) and block size (window size, in sample frames). + * + * The input sample rate should have been already specified at + * construction time. + * + * Return true for successful initialisation, false if the number + * of input channels, step size and/or block size cannot be + * supported. + */ + virtual bool initialise(size_t inputChannels, + size_t stepSize, + size_t blockSize) = 0; + + /** + * Reset the plugin after use, to prepare it for another clean + * run. Not called for the first initialisation (i.e. initialise + * must also do a reset). + */ + virtual void reset() = 0; + + 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(). + * 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. + */ + virtual InputDomain getInputDomain() const = 0; + + /** + * Get the preferred step size (window increment -- the distance + * in sample frames between the start frames of consecutive blocks + * passed to the process() function) for the plugin. This should + * be called before initialise(). + */ + virtual size_t getPreferredStepSize() const = 0; + + /** + * Get the preferred block size (window size -- the number of + * sample frames passed in each block to the process() function). + * This should be called before initialise(). + */ + virtual size_t getPreferredBlockSize() const { return getPreferredStepSize(); } + + /** + * Get the minimum supported number of input channels. + */ + virtual size_t getMinChannelCount() const { return 1; } + + /** + * Get the maximum supported number of input channels. + */ + virtual size_t getMaxChannelCount() const { return 1; } + + struct OutputDescriptor + { + /** + * The name of the output, in computer-usable form. Should be + * reasonably short and without whitespace or punctuation. + */ + std::string name; + + /** + * The human-readable name of the output. + */ + std::string description; + + /** + * The unit of the output, in human-readable form. + */ + std::string unit; + + /** + * True if the output has the same number of values per result + * for every output result. Outputs for which this is false + * are unlikely to be very useful in a general-purpose host. + */ + bool hasFixedValueCount; + + /** + * The number of values per result of the output. Undefined + * if hasFixedValueCount is false. If this is zero, the output + * is point data (i.e. only the time of each output is of + * interest, the value list will be empty). + * + * Note that this gives the number of values of a single + * output result, not of the output stream (which has one more + * dimension: time). + */ + size_t valueCount; + + /** + * The names of each of the values, if appropriate. This is + * always optional. + */ + std::vector valueNames; + + /** + * True if the results in the output have a fixed numeric + * range (minimum and maximum values). Undefined if + * valueCount is zero. + */ + bool hasKnownExtents; + + /** + * Minimum value of the results in the output. Undefined if + * hasKnownExtents is false or valueCount is zero. + */ + float minValue; + + /** + * Maximum value of the results in the output. Undefined if + * hasKnownExtents is false or valueCount is zero. + */ + float maxValue; + + /** + * True if the output values are quantized to a particular + * resolution. Undefined if valueCount is zero. + */ + bool isQuantized; + + /** + * Quantization resolution of the output values (e.g. 1.0 if + * they are all integers). Undefined if isQuantized is false + * or valueCount is zero. + */ + float quantizeStep; + + enum SampleType { + + /// Results from each process() align with that call's block start + OneSamplePerStep, + + /// Results are evenly spaced in time (sampleRate specified below) + FixedSampleRate, + + /// Results are unevenly spaced and have individual timestamps + VariableSampleRate + }; + + /** + * Positioning in time of the output results. + */ + SampleType sampleType; + + /** + * Sample rate of the output results. Undefined if sampleType + * is OneSamplePerStep. + * + * If sampleType is VariableSampleRate and this value is + * non-zero, then it may be used to calculate a resolution for + * the output (i.e. the "duration" of each value, in time). + * It's recommended to set this to zero if that behaviour is + * not desired. + */ + float sampleRate; + }; + + typedef std::vector OutputList; + + /** + * Get the outputs of this plugin. An output's index in this list + * is used as its numeric index when looking it up in the + * FeatureSet returned from the process() call. + */ + virtual OutputList getOutputDescriptors() const = 0; + + struct Feature + { + /** + * True if an output feature has its own timestamp. This is + * mandatory if the output has VariableSampleRate, and is + * likely to be disregarded otherwise. + */ + bool hasTimestamp; + + /** + * Timestamp of the output feature. This is mandatory if the + * output has VariableSampleRate, and is likely to be + * disregarded otherwise. Undefined if hasTimestamp is false. + */ + RealTime timestamp; + + /** + * Results for a single sample of this feature. If the output + * hasFixedValueCount, there must be the same number of values + * as the output's valueCount count. + */ + std::vector values; + + /** + * Label for the sample of this feature. + */ + std::string label; + }; + + typedef std::vector FeatureList; + typedef std::map FeatureSet; // key is output no + + /** + * Process a single block of input data. + * + * If the plugin's inputDomain is TimeDomain, inputBuffers will + * point to one array of floats per input channel, and each of + * these arrays will contain blockSize consecutive audio samples + * (the host will zero-pad as necessary). + * + * If the plugin's inputDomain is FrequencyDomain, inputBuffers + * will point to one array of floats per input channel, and each + * of these arrays will contain blockSize/2 consecutive pairs of + * real and imaginary component floats corresponding to bins + * 0..(blockSize/2-1) of the FFT output. + * + * The timestamp is the real time in seconds of the start of the + * supplied block of samples. + * + * Return any features that have become available after this + * process call. (These do not necessarily have to fall within + * the process block, except for OneSamplePerStep outputs.) + */ + virtual FeatureSet process(float **inputBuffers, + RealTime timestamp) = 0; + + /** + * After all blocks have been processed, calculate and return any + * remaining features derived from the complete input. + */ + virtual FeatureSet getRemainingFeatures() = 0; + + virtual std::string getType() const { return "Feature Extraction Plugin"; } + +protected: + Plugin(float inputSampleRate) : + m_inputSampleRate(inputSampleRate) { } + + float m_inputSampleRate; +}; + +} + +#endif + + + diff -r 000000000000 -r 6479539d1b32 sdk/PluginAdapter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/PluginAdapter.cpp Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,473 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 "PluginAdapter.h" + +namespace Vamp { + +PluginAdapterBase::PluginAdapterBase() : + m_populated(false) +{ +} + +const VampPluginDescriptor * +PluginAdapterBase::getDescriptor() +{ + if (m_populated) return &m_descriptor; + + Plugin *plugin = createPlugin(48000); + + m_parameters = plugin->getParameterDescriptors(); + m_programs = plugin->getPrograms(); + + m_descriptor.name = strdup(plugin->getName().c_str()); + m_descriptor.description = strdup(plugin->getDescription().c_str()); + m_descriptor.maker = strdup(plugin->getMaker().c_str()); + m_descriptor.pluginVersion = plugin->getPluginVersion(); + m_descriptor.copyright = strdup(plugin->getCopyright().c_str()); + + m_descriptor.parameterCount = m_parameters.size(); + m_descriptor.parameters = (const VampParameterDescriptor **) + malloc(m_parameters.size() * sizeof(VampParameterDescriptor)); + + for (unsigned int i = 0; i < m_parameters.size(); ++i) { + VampParameterDescriptor *desc = (VampParameterDescriptor *) + malloc(sizeof(VampParameterDescriptor)); + desc->name = strdup(m_parameters[i].name.c_str()); + desc->description = strdup(m_parameters[i].description.c_str()); + desc->unit = strdup(m_parameters[i].unit.c_str()); + desc->minValue = m_parameters[i].minValue; + desc->maxValue = m_parameters[i].maxValue; + desc->defaultValue = m_parameters[i].defaultValue; + desc->isQuantized = m_parameters[i].isQuantized; + desc->quantizeStep = m_parameters[i].quantizeStep; + m_descriptor.parameters[i] = desc; + } + + m_descriptor.programCount = m_programs.size(); + m_descriptor.programs = (const char **) + malloc(m_programs.size() * sizeof(const char *)); + + for (unsigned int i = 0; i < m_programs.size(); ++i) { + m_descriptor.programs[i] = strdup(m_programs[i].c_str()); + } + + if (plugin->getInputDomain() == Plugin::FrequencyDomain) { + m_descriptor.inputDomain = vampFrequencyDomain; + } else { + m_descriptor.inputDomain = vampTimeDomain; + } + + m_descriptor.instantiate = vampInstantiate; + m_descriptor.cleanup = vampCleanup; + m_descriptor.initialise = vampInitialise; + m_descriptor.reset = vampReset; + m_descriptor.getParameter = vampGetParameter; + m_descriptor.setParameter = vampSetParameter; + m_descriptor.getCurrentProgram = vampGetCurrentProgram; + m_descriptor.selectProgram = vampSelectProgram; + m_descriptor.getPreferredStepSize = vampGetPreferredStepSize; + m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize; + m_descriptor.getMinChannelCount = vampGetMinChannelCount; + m_descriptor.getMaxChannelCount = vampGetMaxChannelCount; + m_descriptor.getOutputCount = vampGetOutputCount; + m_descriptor.getOutputDescriptor = vampGetOutputDescriptor; + m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor; + m_descriptor.process = vampProcess; + m_descriptor.getRemainingFeatures = vampGetRemainingFeatures; + m_descriptor.releaseFeatureSet = vampReleaseFeatureSet; + + m_adapterMap[&m_descriptor] = this; + + delete plugin; + + m_populated = true; + return &m_descriptor; +} + +PluginAdapterBase::~PluginAdapterBase() +{ + if (!m_populated) return; + + free((void *)m_descriptor.name); + free((void *)m_descriptor.description); + free((void *)m_descriptor.maker); + free((void *)m_descriptor.copyright); + + for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) { + const VampParameterDescriptor *desc = m_descriptor.parameters[i]; + free((void *)desc->name); + free((void *)desc->description); + free((void *)desc->unit); + } + free((void *)m_descriptor.parameters); + + for (unsigned int i = 0; i < m_descriptor.programCount; ++i) { + free((void *)m_descriptor.programs[i]); + } + free((void *)m_descriptor.programs); + + m_adapterMap.erase(&m_descriptor); +} + +PluginAdapterBase * +PluginAdapterBase::lookupAdapter(VampPluginHandle handle) +{ + AdapterMap::const_iterator i = m_adapterMap.find(handle); + if (i == m_adapterMap.end()) return 0; + return i->second; +} + +VampPluginHandle +PluginAdapterBase::vampInstantiate(const VampPluginDescriptor *desc, + float inputSampleRate) +{ + if (m_adapterMap.find(desc) == m_adapterMap.end()) return 0; + PluginAdapterBase *adapter = m_adapterMap[desc]; + if (desc != &adapter->m_descriptor) return 0; + + Plugin *plugin = adapter->createPlugin(inputSampleRate); + if (plugin) { + m_adapterMap[plugin] = adapter; + } + + return plugin; +} + +void +PluginAdapterBase::vampCleanup(VampPluginHandle handle) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) { + delete ((Plugin *)handle); + return; + } + adapter->cleanup(((Plugin *)handle)); +} + +int +PluginAdapterBase::vampInitialise(VampPluginHandle handle, + unsigned int channels, + unsigned int stepSize, + unsigned int blockSize) +{ + bool result = ((Plugin *)handle)->initialise + (channels, stepSize, blockSize); + return result ? 1 : 0; +} + +void +PluginAdapterBase::vampReset(VampPluginHandle handle) +{ + ((Plugin *)handle)->reset(); +} + +float +PluginAdapterBase::vampGetParameter(VampPluginHandle handle, + int param) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0.0; + Plugin::ParameterList &list = adapter->m_parameters; + return ((Plugin *)handle)->getParameter(list[param].name); +} + +void +PluginAdapterBase::vampSetParameter(VampPluginHandle handle, + int param, float value) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return; + Plugin::ParameterList &list = adapter->m_parameters; + ((Plugin *)handle)->setParameter(list[param].name, value); +} + +unsigned int +PluginAdapterBase::vampGetCurrentProgram(VampPluginHandle handle) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0; + Plugin::ProgramList &list = adapter->m_programs; + std::string program = ((Plugin *)handle)->getCurrentProgram(); + for (unsigned int i = 0; i < list.size(); ++i) { + if (list[i] == program) return i; + } + return 0; +} + +void +PluginAdapterBase::vampSelectProgram(VampPluginHandle handle, + unsigned int program) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return; + Plugin::ProgramList &list = adapter->m_programs; + ((Plugin *)handle)->selectProgram(list[program]); +} + +unsigned int +PluginAdapterBase::vampGetPreferredStepSize(VampPluginHandle handle) +{ + return ((Plugin *)handle)->getPreferredStepSize(); +} + +unsigned int +PluginAdapterBase::vampGetPreferredBlockSize(VampPluginHandle handle) +{ + return ((Plugin *)handle)->getPreferredBlockSize(); +} + +unsigned int +PluginAdapterBase::vampGetMinChannelCount(VampPluginHandle handle) +{ + return ((Plugin *)handle)->getMinChannelCount(); +} + +unsigned int +PluginAdapterBase::vampGetMaxChannelCount(VampPluginHandle handle) +{ + return ((Plugin *)handle)->getMaxChannelCount(); +} + +unsigned int +PluginAdapterBase::vampGetOutputCount(VampPluginHandle handle) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->getOutputCount((Plugin *)handle); +} + +VampOutputDescriptor * +PluginAdapterBase::vampGetOutputDescriptor(VampPluginHandle handle, + unsigned int i) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->getOutputDescriptor((Plugin *)handle, i); +} + +void +PluginAdapterBase::vampReleaseOutputDescriptor(VampOutputDescriptor *desc) +{ + if (desc->name) free((void *)desc->name); + if (desc->description) free((void *)desc->description); + if (desc->unit) free((void *)desc->unit); + for (unsigned int i = 0; i < desc->valueCount; ++i) { + free((void *)desc->valueNames[i]); + } + if (desc->valueNames) free((void *)desc->valueNames); + free((void *)desc); +} + +VampFeatureList ** +PluginAdapterBase::vampProcess(VampPluginHandle handle, + float **inputBuffers, + int sec, + int nsec) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->process((Plugin *)handle, + inputBuffers, sec, nsec); +} + +VampFeatureList ** +PluginAdapterBase::vampGetRemainingFeatures(VampPluginHandle handle) +{ + PluginAdapterBase *adapter = lookupAdapter(handle); + if (!adapter) return 0; + return adapter->getRemainingFeatures((Plugin *)handle); +} + +void +PluginAdapterBase::vampReleaseFeatureSet(VampFeatureList **fs) +{ + if (!fs) return; + for (unsigned int i = 0; fs[i]; ++i) { + for (unsigned int j = 0; j < fs[i]->featureCount; ++j) { + VampFeature *feature = &fs[i]->features[j]; + if (feature->values) free((void *)feature->values); + if (feature->label) free((void *)feature->label); + free((void *)feature); + } + if (fs[i]->features) free((void *)fs[i]->features); + free((void *)fs[i]); + } + free((void *)fs); +} + +void +PluginAdapterBase::cleanup(Plugin *plugin) +{ + if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) { + delete m_pluginOutputs[plugin]; + m_pluginOutputs.erase(plugin); + } + m_adapterMap.erase(plugin); + delete ((Plugin *)plugin); +} + +void +PluginAdapterBase::checkOutputMap(Plugin *plugin) +{ + if (!m_pluginOutputs[plugin]) { + m_pluginOutputs[plugin] = new Plugin::OutputList + (plugin->getOutputDescriptors()); + } +} + +unsigned int +PluginAdapterBase::getOutputCount(Plugin *plugin) +{ + checkOutputMap(plugin); + return m_pluginOutputs[plugin]->size(); +} + +VampOutputDescriptor * +PluginAdapterBase::getOutputDescriptor(Plugin *plugin, + unsigned int i) +{ + checkOutputMap(plugin); + Plugin::OutputDescriptor &od = + (*m_pluginOutputs[plugin])[i]; + + VampOutputDescriptor *desc = (VampOutputDescriptor *) + malloc(sizeof(VampOutputDescriptor)); + + desc->name = strdup(od.name.c_str()); + desc->description = strdup(od.description.c_str()); + desc->unit = strdup(od.unit.c_str()); + desc->hasFixedValueCount = od.hasFixedValueCount; + desc->valueCount = od.valueCount; + + desc->valueNames = (const char **) + malloc(od.valueCount * sizeof(const char *)); + + for (unsigned int i = 0; i < od.valueCount; ++i) { + if (i < od.valueNames.size()) { + desc->valueNames[i] = strdup(od.valueNames[i].c_str()); + } else { + desc->valueNames[i] = 0; + } + } + + desc->hasKnownExtents = od.hasKnownExtents; + desc->minValue = od.minValue; + desc->maxValue = od.maxValue; + desc->isQuantized = od.isQuantized; + desc->quantizeStep = od.quantizeStep; + + switch (od.sampleType) { + case Plugin::OutputDescriptor::OneSamplePerStep: + desc->sampleType = vampOneSamplePerStep; break; + case Plugin::OutputDescriptor::FixedSampleRate: + desc->sampleType = vampFixedSampleRate; break; + case Plugin::OutputDescriptor::VariableSampleRate: + desc->sampleType = vampVariableSampleRate; break; + } + + desc->sampleRate = od.sampleRate; + + return desc; +} + +VampFeatureList ** +PluginAdapterBase::process(Plugin *plugin, + float **inputBuffers, + int sec, int nsec) +{ + RealTime rt(sec, nsec); + return convertFeatures(plugin->process(inputBuffers, rt)); +} + +VampFeatureList ** +PluginAdapterBase::getRemainingFeatures(Plugin *plugin) +{ + return convertFeatures(plugin->getRemainingFeatures()); +} + +VampFeatureList ** +PluginAdapterBase::convertFeatures(const Plugin::FeatureSet &features) +{ + unsigned int n = 0; + if (features.begin() != features.end()) { + Plugin::FeatureSet::const_iterator i = features.end(); + --i; + n = i->first + 1; + } + + if (!n) return 0; + + VampFeatureList **fs = (VampFeatureList **) + malloc((n + 1) * sizeof(VampFeatureList *)); + + for (unsigned int i = 0; i < n; ++i) { + fs[i] = (VampFeatureList *)malloc(sizeof(VampFeatureList)); + if (features.find(i) == features.end()) { + fs[i]->featureCount = 0; + fs[i]->features = 0; + } else { + Plugin::FeatureSet::const_iterator fi = + features.find(i); + const Plugin::FeatureList &fl = fi->second; + fs[i]->featureCount = fl.size(); + fs[i]->features = (VampFeature *)malloc(fl.size() * + sizeof(VampFeature)); + for (unsigned int j = 0; j < fl.size(); ++j) { + fs[i]->features[j].hasTimestamp = fl[j].hasTimestamp; + fs[i]->features[j].sec = fl[j].timestamp.sec; + fs[i]->features[j].nsec = fl[j].timestamp.nsec; + fs[i]->features[j].valueCount = fl[j].values.size(); + fs[i]->features[j].values = (float *)malloc + (fs[i]->features[j].valueCount * sizeof(float)); + for (unsigned int k = 0; k < fs[i]->features[j].valueCount; ++k) { + fs[i]->features[j].values[k] = fl[j].values[k]; + } + fs[i]->features[j].label = strdup(fl[j].label.c_str()); + } + } + } + + fs[n] = 0; + + return fs; +} + +PluginAdapterBase::AdapterMap +PluginAdapterBase::m_adapterMap; + +} + diff -r 000000000000 -r 6479539d1b32 sdk/PluginAdapter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/PluginAdapter.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,147 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM 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 _PLUGIN_ADAPTER_H_ +#define _PLUGIN_ADAPTER_H_ + +#include "vamp.h" +#include "Plugin.h" + +#include + +namespace Vamp { + +class PluginAdapterBase +{ +public: + virtual ~PluginAdapterBase(); + const VampPluginDescriptor *getDescriptor(); + +protected: + PluginAdapterBase(); + + virtual Plugin *createPlugin(float inputSampleRate) = 0; + + static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc, + float inputSampleRate); + + static void vampCleanup(VampPluginHandle handle); + + static int vampInitialise(VampPluginHandle handle, unsigned int channels, + unsigned int stepSize, unsigned int blockSize); + + static void vampReset(VampPluginHandle handle); + + static float vampGetParameter(VampPluginHandle handle, int param); + static void vampSetParameter(VampPluginHandle handle, int param, float value); + + static unsigned int vampGetCurrentProgram(VampPluginHandle handle); + static void vampSelectProgram(VampPluginHandle handle, unsigned int program); + + static unsigned int vampGetPreferredStepSize(VampPluginHandle handle); + static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle); + static unsigned int vampGetMinChannelCount(VampPluginHandle handle); + static unsigned int vampGetMaxChannelCount(VampPluginHandle handle); + + static unsigned int vampGetOutputCount(VampPluginHandle handle); + + static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle, + unsigned int i); + + static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc); + + static VampFeatureList **vampProcess(VampPluginHandle handle, + float **inputBuffers, + int sec, + int nsec); + + static VampFeatureList **vampGetRemainingFeatures(VampPluginHandle handle); + + static void vampReleaseFeatureSet(VampFeatureList **fs); + + void cleanup(Plugin *plugin); + void checkOutputMap(Plugin *plugin); + unsigned int getOutputCount(Plugin *plugin); + VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, + unsigned int i); + VampFeatureList **process(Plugin *plugin, + float **inputBuffers, + int sec, int nsec); + VampFeatureList **getRemainingFeatures(Plugin *plugin); + VampFeatureList **convertFeatures(const Plugin::FeatureSet &features); + + typedef std::map AdapterMap; + static AdapterMap m_adapterMap; + static PluginAdapterBase *lookupAdapter(VampPluginHandle); + + bool m_populated; + VampPluginDescriptor m_descriptor; + Plugin::ParameterList m_parameters; + Plugin::ProgramList m_programs; + + typedef std::map OutputMap; + OutputMap m_pluginOutputs; + + typedef std::map FeatureBufferMap; + FeatureBufferMap m_pluginFeatures; +}; + +template +class PluginAdapter : public PluginAdapterBase +{ +public: + PluginAdapter() : PluginAdapterBase() { } + ~PluginAdapter() { } + +protected: + Plugin *createPlugin(float inputSampleRate) { + P *p = new P(inputSampleRate); + Plugin *plugin = dynamic_cast(p); + if (!plugin) { + std::cerr << "ERROR: PluginAdapter::createPlugin: " + << "Template type is not a plugin!" + << std::endl; + delete p; + return 0; + } + return plugin; + } +}; + +} + +#endif + diff -r 000000000000 -r 6479539d1b32 sdk/PluginBase.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/PluginBase.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,169 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _VAMP_PLUGIN_BASE_H_ +#define _VAMP_PLUGIN_BASE_H_ + +#include +#include + +namespace Vamp { + +/** + * A base class for plugins with optional configurable parameters, + * programs, etc. + * + * This does not provide the necessary interfaces to instantiate or + * run a plugin -- that depends on the plugin subclass, as different + * plugin types may have quite different operating structures. This + * class just specifies the necessary interface to show editable + * controls for the plugin to the user. + */ + +class PluginBase +{ +public: + /** + * Get the computer-usable name of the plugin. This should be + * reasonably short and contain no whitespace or punctuation + * characters. It may be shown to the user, but it won't be the + * main method for a user to identify a plugin (that will be the + * description, below). + */ + virtual std::string getName() const = 0; + + /** + * Get a human-readable description of the plugin. This should be + * self-contained, as it may be shown to the user in isolation + * without also showing the plugin's "name". + */ + virtual std::string getDescription() const = 0; + + /** + * Get the name of the author or vendor of the plugin in + * human-readable form. + */ + virtual std::string getMaker() const = 0; + + /** + * Get the version number of the plugin. + */ + virtual int getPluginVersion() const = 0; + + /** + * Get the copyright statement or licensing summary of the plugin. + */ + virtual std::string getCopyright() const = 0; + + /** + * Get the type of plugin (e.g. DSSI, etc). This is likely to be + * implemented by the immediate subclass, not by actual plugins. + */ + virtual std::string getType() const = 0; + + + struct ParameterDescriptor + { + /** + * The name of the parameter, in computer-usable form. Should + * be reasonably short, and may only contain the characters + * [a-zA-Z0-9_]. + */ + std::string name; + + /** + * The human-readable name of the parameter. + */ + std::string description; + + /** + * The unit of the parameter, in human-readable form. + */ + std::string unit; + + /** + * The minimum value of the parameter. + */ + float minValue; + + /** + * The maximum value of the parameter. + */ + float maxValue; + + /** + * The default value of the parameter. + */ + float defaultValue; + + /** + * True if the parameter values are quantized to a particular + * resolution. + */ + bool isQuantized; + + /** + * Quantization resolution of the parameter values (e.g. 1.0 + * if they are all integers). Undefined if isQuantized is + * false. + */ + float quantizeStep; + }; + + typedef std::vector ParameterList; + + /** + * Get the controllable parameters of this plugin. + */ + virtual ParameterList getParameterDescriptors() const { + return ParameterList(); + } + + /** + * Get the value of a named parameter. The argument is the name + * field from that parameter's descriptor. + */ + virtual float getParameter(std::string) const { return 0.0; } + + /** + * Set a named parameter. The first argument is the name field + * from that parameter's descriptor. + */ + virtual void setParameter(std::string, float) { } + + + typedef std::vector ProgramList; + + /** + * Get the program settings available in this plugin. + * The programs must have unique names. + */ + virtual ProgramList getPrograms() const { return ProgramList(); } + + /** + * Get the current program. + */ + virtual std::string getCurrentProgram() const { return ""; } + + /** + * Select a program. (If the given program name is not one of the + * available programs, do nothing.) + */ + virtual void selectProgram(std::string) { } +}; + +} + +#endif diff -r 000000000000 -r 6479539d1b32 sdk/RealTime.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/RealTime.cpp Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,248 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +/* + This is a modified version of a source file from the + Rosegarden MIDI and audio sequencer and notation editor. + This file copyright 2000-2006 Chris Cannam; relicensed as detailed above +*/ + +#include + +#if (__GNUC__ < 3) +#include +#define stringstream strstream +#else +#include +#endif + +using std::cerr; +using std::endl; + +#include "RealTime.h" +#include "sys/time.h" + +namespace Vamp { + +// A RealTime consists of two ints that must be at least 32 bits each. +// A signed 32-bit int can store values exceeding +/- 2 billion. This +// means we can safely use our lower int for nanoseconds, as there are +// 1 billion nanoseconds in a second and we need to handle double that +// because of the implementations of addition etc that we use. +// +// The maximum valid RealTime on a 32-bit system is somewhere around +// 68 years: 999999999 nanoseconds longer than the classic Unix epoch. + +#define ONE_BILLION 1000000000 + +RealTime::RealTime(int s, int n) : + sec(s), nsec(n) +{ + if (sec == 0) { + while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } + while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } + } else if (sec < 0) { + while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; } + while (nsec > 0) { nsec -= ONE_BILLION; ++sec; } + } else { + while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; } + while (nsec < 0) { nsec += ONE_BILLION; --sec; } + } +} + +RealTime +RealTime::fromSeconds(double sec) +{ + return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION)); +} + +RealTime +RealTime::fromMilliseconds(int msec) +{ + return RealTime(msec / 1000, (msec % 1000) * 1000000); +} + +RealTime +RealTime::fromTimeval(const struct timeval &tv) +{ + return RealTime(tv.tv_sec, tv.tv_usec * 1000); +} + +std::ostream &operator<<(std::ostream &out, const RealTime &rt) +{ + if (rt < RealTime::zeroTime) { + out << "-"; + } else { + out << " "; + } + + int s = (rt.sec < 0 ? -rt.sec : rt.sec); + int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec); + + out << s << "."; + + int nn(n); + if (nn == 0) out << "00000000"; + else while (nn < (ONE_BILLION / 10)) { + out << "0"; + nn *= 10; + } + + out << n << "R"; + return out; +} + +std::string +RealTime::toString() const +{ + std::stringstream out; + out << *this; + +#if (__GNUC__ < 3) + out << std::ends; +#endif + + std::string s = out.str(); + + // remove trailing R + return s.substr(0, s.length() - 1); +} + +std::string +RealTime::toText(bool fixedDp) const +{ + if (*this < RealTime::zeroTime) return "-" + (-*this).toText(); + + std::stringstream out; + + if (sec >= 3600) { + out << (sec / 3600) << ":"; + } + + if (sec >= 60) { + out << (sec % 3600) / 60 << ":"; + } + + if (sec >= 10) { + out << ((sec % 60) / 10); + } + + out << (sec % 10); + + int ms = msec(); + + if (ms != 0) { + out << "."; + out << (ms / 100); + ms = ms % 100; + if (ms != 0) { + out << (ms / 10); + ms = ms % 10; + } else if (fixedDp) { + out << "0"; + } + if (ms != 0) { + out << ms; + } else if (fixedDp) { + out << "0"; + } + } else if (fixedDp) { + out << ".000"; + } + +#if (__GNUC__ < 3) + out << std::ends; +#endif + + std::string s = out.str(); + + return s; +} + + +RealTime +RealTime::operator/(int d) const +{ + int secdiv = sec / d; + int secrem = sec % d; + + double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d; + + return RealTime(secdiv, int(nsecdiv + 0.5)); +} + +double +RealTime::operator/(const RealTime &r) const +{ + double lTotal = double(sec) * ONE_BILLION + double(nsec); + double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec); + + if (rTotal == 0) return 0.0; + else return lTotal/rTotal; +} + +long +RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate) +{ + if (time < zeroTime) return -realTime2Frame(-time, sampleRate); + + // We like integers. The last term is always zero unless the + // sample rate is greater than 1MHz, but hell, you never know... + + long frame = + time.sec * sampleRate + + (time.msec() * sampleRate) / 1000 + + ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 + + ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000; + + return frame; +} + +RealTime +RealTime::frame2RealTime(long frame, unsigned int sampleRate) +{ + if (frame < 0) return -frame2RealTime(-frame, sampleRate); + + RealTime rt; + rt.sec = frame / long(sampleRate); + frame -= rt.sec * long(sampleRate); + rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000); + return rt; +} + +const RealTime RealTime::zeroTime(0,0); + +} diff -r 000000000000 -r 6479539d1b32 sdk/RealTime.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdk/RealTime.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,146 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +/* + This is a modified version of a source file from the + Rosegarden MIDI and audio sequencer and notation editor. + This file copyright 2000-2006 Chris Cannam; relicensed as detailed above +*/ + +#ifndef _REAL_TIME_H_ +#define _REAL_TIME_H_ + +#include +#include + +struct timeval; + +namespace Vamp { + +/** + * RealTime represents time values to nanosecond precision + * with accurate arithmetic and frame-rate conversion functions. + */ + +struct RealTime +{ + int sec; + int nsec; + + int usec() const { return nsec / 1000; } + int msec() const { return nsec / 1000000; } + + RealTime(): sec(0), nsec(0) {} + RealTime(int s, int n); + + RealTime(const RealTime &r) : + sec(r.sec), nsec(r.nsec) { } + + static RealTime fromSeconds(double sec); + static RealTime fromMilliseconds(int msec); + static RealTime fromTimeval(const struct timeval &); + + RealTime &operator=(const RealTime &r) { + sec = r.sec; nsec = r.nsec; return *this; + } + + RealTime operator+(const RealTime &r) const { + return RealTime(sec + r.sec, nsec + r.nsec); + } + RealTime operator-(const RealTime &r) const { + return RealTime(sec - r.sec, nsec - r.nsec); + } + RealTime operator-() const { + return RealTime(-sec, -nsec); + } + + bool operator <(const RealTime &r) const { + if (sec == r.sec) return nsec < r.nsec; + else return sec < r.sec; + } + + bool operator >(const RealTime &r) const { + if (sec == r.sec) return nsec > r.nsec; + else return sec > r.sec; + } + + bool operator==(const RealTime &r) const { + return (sec == r.sec && nsec == r.nsec); + } + + bool operator!=(const RealTime &r) const { + return !(r == *this); + } + + bool operator>=(const RealTime &r) const { + if (sec == r.sec) return nsec >= r.nsec; + else return sec >= r.sec; + } + + bool operator<=(const RealTime &r) const { + if (sec == r.sec) return nsec <= r.nsec; + else return sec <= r.sec; + } + + RealTime operator/(int d) const; + + // Find the fractional difference between times + // + double operator/(const RealTime &r) const; + + // Return a human-readable debug-type string to full precision + // (probably not a format to show to a user directly) + // + std::string toString() const; + + // Return a user-readable string to the nearest millisecond + // in a form like HH:MM:SS.mmm + // + std::string toText(bool fixedDp = false) const; + + // Convenience functions for handling sample frames + // + static long realTime2Frame(const RealTime &r, unsigned int sampleRate); + static RealTime frame2RealTime(long frame, unsigned int sampleRate); + + static const RealTime zeroTime; +}; + +std::ostream &operator<<(std::ostream &out, const RealTime &rt); + +} + +#endif diff -r 000000000000 -r 6479539d1b32 vamp/vamp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp/vamp.h Fri Mar 31 14:21:51 2006 +0000 @@ -0,0 +1,178 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp + + An API for audio analysis and feature extraction plugins. + + Centre for Digital Music, Queen Mary, University of London. + Copyright 2006 Chris Cannam. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the names of the Centre for + Digital Music; Queen Mary, University of London; and Chris Cannam + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization. +*/ + +#ifndef VAMP_HEADER_INCLUDED +#define VAMP_HEADER_INCLUDED + +/* + * C language API for Vamp plugins. + * + * This is the formal plugin API for Vamp. Plugin authors may prefer + * to use the C++ classes defined in the sdk directory, instead of + * using this API directly. There is an adapter class provided that + * makes C++ plugins available using this C API with relatively little + * work. See the example plugins in the examples directory. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _VampParameterDescriptor +{ + const char *name; + const char *description; + const char *unit; + float minValue; + float maxValue; + float defaultValue; + int isQuantized; + float quantizeStep; + +} VampParameterDescriptor; + +typedef enum +{ + vampOneSamplePerStep, + vampFixedSampleRate, + vampVariableSampleRate + +} VampSampleType; + +typedef struct _VampOutputDescriptor +{ + const char *name; + const char *description; + const char *unit; + int hasFixedValueCount; + unsigned int valueCount; + const char **valueNames; + int hasKnownExtents; + float minValue; + float maxValue; + int isQuantized; + float quantizeStep; + VampSampleType sampleType; + float sampleRate; + +} VampOutputDescriptor; + +typedef struct _VampFeature +{ + int hasTimestamp; + int sec; + int nsec; + unsigned int valueCount; + float *values; + char *label; + +} VampFeature; + +typedef struct _VampFeatureList +{ + unsigned int featureCount; + VampFeature *features; + +} VampFeatureList; + +typedef enum +{ + vampTimeDomain, + vampFrequencyDomain + +} VampInputDomain; + +typedef void *VampPluginHandle; + +typedef struct _VampPluginDescriptor +{ + const char *name; + const char *description; + const char *maker; + int pluginVersion; + const char *copyright; + unsigned int parameterCount; + const VampParameterDescriptor **parameters; + unsigned int programCount; + const char **programs; + VampInputDomain inputDomain; + + VampPluginHandle (*instantiate)(const struct _VampPluginDescriptor *, + float inputSampleRate); + + void (*cleanup)(VampPluginHandle); + + int (*initialise)(VampPluginHandle, + unsigned int inputChannels, + unsigned int stepSize, + unsigned int blockSize); + + void (*reset)(VampPluginHandle); + + float (*getParameter)(VampPluginHandle, int); + void (*setParameter)(VampPluginHandle, int, float); + + unsigned int (*getCurrentProgram)(VampPluginHandle); + void (*selectProgram)(VampPluginHandle, unsigned int); + + unsigned int (*getPreferredStepSize)(VampPluginHandle); + unsigned int (*getPreferredBlockSize)(VampPluginHandle); + unsigned int (*getMinChannelCount)(VampPluginHandle); + unsigned int (*getMaxChannelCount)(VampPluginHandle); + + unsigned int (*getOutputCount)(VampPluginHandle); + VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle, + unsigned int); + void (*releaseOutputDescriptor)(VampOutputDescriptor *); + + VampFeatureList **(*process)(VampPluginHandle, + float **inputBuffers, + int sec, + int nsec); + VampFeatureList **(*getRemainingFeatures)(VampPluginHandle); + void (*releaseFeatureSet)(VampFeatureList **); + +} VampPluginDescriptor; + +const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int index); + +typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction)(unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif