annotate sdk/Plugin.h @ 0:6479539d1b32

* Importing first cut of Sonic Visualiser's Vamp plugin format SDK
author cannam
date Fri, 31 Mar 2006 14:21:51 +0000
parents
children
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 Vamp
cannam@0 5
cannam@0 6 An API for audio analysis and feature extraction plugins.
cannam@0 7
cannam@0 8 Centre for Digital Music, Queen Mary, University of London.
cannam@0 9 Copyright 2006 Chris Cannam.
cannam@0 10
cannam@0 11 Permission is hereby granted, free of charge, to any person
cannam@0 12 obtaining a copy of this software and associated documentation
cannam@0 13 files (the "Software"), to deal in the Software without
cannam@0 14 restriction, including without limitation the rights to use, copy,
cannam@0 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@0 16 of the Software, and to permit persons to whom the Software is
cannam@0 17 furnished to do so, subject to the following conditions:
cannam@0 18
cannam@0 19 The above copyright notice and this permission notice shall be
cannam@0 20 included in all copies or substantial portions of the Software.
cannam@0 21
cannam@0 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@0 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@0 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@0 25 NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
cannam@0 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@0 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@0 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@0 29
cannam@0 30 Except as contained in this notice, the names of the Centre for
cannam@0 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@0 32 shall not be used in advertising or otherwise to promote the sale,
cannam@0 33 use or other dealings in this Software without prior written
cannam@0 34 authorization.
cannam@0 35 */
cannam@0 36
cannam@0 37 #ifndef _VAMP_PLUGIN_H_
cannam@0 38 #define _VAMP_PLUGIN_H_
cannam@0 39
cannam@0 40 #include "PluginBase.h"
cannam@0 41 #include "RealTime.h"
cannam@0 42
cannam@0 43 #include <string>
cannam@0 44 #include <vector>
cannam@0 45 #include <map>
cannam@0 46
cannam@0 47 namespace Vamp {
cannam@0 48
cannam@0 49 /**
cannam@0 50 * Vamp::Plugin is a base class for plugin instance classes
cannam@0 51 * that provide feature extraction from audio or related data.
cannam@0 52 *
cannam@0 53 * In most cases, the input will be audio and the output will be a
cannam@0 54 * stream of derived data at a lower sampling resolution than the
cannam@0 55 * input.
cannam@0 56 *
cannam@0 57 * Note that this class inherits several abstract methods from
cannam@0 58 * PluginBase, that must be implemented by the subclass.
cannam@0 59 */
cannam@0 60
cannam@0 61 /**
cannam@0 62 * Plugin Lifecycle
cannam@0 63 * ================
cannam@0 64 *
cannam@0 65 * Feature extraction plugins are managed differently from real-time
cannam@0 66 * plugins (such as VST effects). The main difference is that the
cannam@0 67 * parameters for a feature extraction plugin are configured before
cannam@0 68 * the plugin is used, and do not change during use.
cannam@0 69 *
cannam@0 70 * 1. Host constructs the plugin, passing it the input sample rate.
cannam@0 71 * The plugin may do basic initialisation, but should not do anything
cannam@0 72 * computationally expensive at this point.
cannam@0 73 *
cannam@0 74 * 2. Host may query the plugin's available outputs.
cannam@0 75 *
cannam@0 76 * 3. Host queries programs and parameter descriptors, and may set
cannam@0 77 * some or all of them. Parameters that are not explicitly set should
cannam@0 78 * take their default values as specified in the parameter descriptor.
cannam@0 79 * When a program is set, the parameter values may change and the host
cannam@0 80 * will re-query them to check.
cannam@0 81 *
cannam@0 82 * 4. Host queries the preferred step size, block size, number of
cannam@0 83 * channels, and the number of values per feature for the plugin's
cannam@0 84 * outputs. These may all vary depending on the parameter values.
cannam@0 85 * (Note however that you cannot make the number of distinct outputs
cannam@0 86 * dependent on parameter values; nor can you make any of these depend
cannam@0 87 * on the number of input channels.)
cannam@0 88 *
cannam@0 89 * 5. Plugin is properly initialised with a call to initialise. This
cannam@0 90 * fixes the step size, block size, and number of channels, as well as
cannam@0 91 * all of the parameter and program settings. If the values passed in
cannam@0 92 * to initialise do not match the plugin's advertised preferred values
cannam@0 93 * from step 4, the plugin may refuse to initialise and return false
cannam@0 94 * (although if possible it should accept the new values).
cannam@0 95 *
cannam@0 96 * 6. Host will repeatedly call the process method to pass in blocks
cannam@0 97 * of input data. This method may return features extracted from that
cannam@0 98 * data (if the plugin is causal).
cannam@0 99 *
cannam@0 100 * 7. Host will call getRemainingFeatures exactly once, after all the
cannam@0 101 * input data has been processed. This may return any non-causal or
cannam@0 102 * leftover features.
cannam@0 103 *
cannam@0 104 * 8. At any point after initialise was called, the host may
cannam@0 105 * optionally call the reset method and restart processing. (This
cannam@0 106 * does not mean it can change the parameters, which are fixed from
cannam@0 107 * initialise until destruction.)
cannam@0 108 *
cannam@0 109 * A plugin does not need to handle the case where setParameter or
cannam@0 110 * selectProgram is called after initialise has been called. It's the
cannam@0 111 * host's responsibility not to do that.
cannam@0 112 */
cannam@0 113
cannam@0 114 class Plugin : public PluginBase
cannam@0 115 {
cannam@0 116 public:
cannam@0 117 /**
cannam@0 118 * Initialise a plugin to prepare it for use with the given number
cannam@0 119 * of input channels, step size (window increment, in sample
cannam@0 120 * frames) and block size (window size, in sample frames).
cannam@0 121 *
cannam@0 122 * The input sample rate should have been already specified at
cannam@0 123 * construction time.
cannam@0 124 *
cannam@0 125 * Return true for successful initialisation, false if the number
cannam@0 126 * of input channels, step size and/or block size cannot be
cannam@0 127 * supported.
cannam@0 128 */
cannam@0 129 virtual bool initialise(size_t inputChannels,
cannam@0 130 size_t stepSize,
cannam@0 131 size_t blockSize) = 0;
cannam@0 132
cannam@0 133 /**
cannam@0 134 * Reset the plugin after use, to prepare it for another clean
cannam@0 135 * run. Not called for the first initialisation (i.e. initialise
cannam@0 136 * must also do a reset).
cannam@0 137 */
cannam@0 138 virtual void reset() = 0;
cannam@0 139
cannam@0 140 enum InputDomain { TimeDomain, FrequencyDomain };
cannam@0 141
cannam@0 142 /**
cannam@0 143 * Get the plugin's required input domain. If this is TimeDomain,
cannam@0 144 * the samples provided to the process() function (below) will be
cannam@0 145 * in the time domain, as for a traditional audio processing
cannam@0 146 * plugin. If this is FrequencyDomain, the host will carry out a
cannam@0 147 * windowed FFT of size equal to the negotiated block size on the
cannam@0 148 * data before passing the frequency bin data in to process().
cannam@0 149 * The plugin does not get to choose the window type -- the host
cannam@0 150 * will either let the user do so, or will use a Hanning window.
cannam@0 151 */
cannam@0 152 virtual InputDomain getInputDomain() const = 0;
cannam@0 153
cannam@0 154 /**
cannam@0 155 * Get the preferred step size (window increment -- the distance
cannam@0 156 * in sample frames between the start frames of consecutive blocks
cannam@0 157 * passed to the process() function) for the plugin. This should
cannam@0 158 * be called before initialise().
cannam@0 159 */
cannam@0 160 virtual size_t getPreferredStepSize() const = 0;
cannam@0 161
cannam@0 162 /**
cannam@0 163 * Get the preferred block size (window size -- the number of
cannam@0 164 * sample frames passed in each block to the process() function).
cannam@0 165 * This should be called before initialise().
cannam@0 166 */
cannam@0 167 virtual size_t getPreferredBlockSize() const { return getPreferredStepSize(); }
cannam@0 168
cannam@0 169 /**
cannam@0 170 * Get the minimum supported number of input channels.
cannam@0 171 */
cannam@0 172 virtual size_t getMinChannelCount() const { return 1; }
cannam@0 173
cannam@0 174 /**
cannam@0 175 * Get the maximum supported number of input channels.
cannam@0 176 */
cannam@0 177 virtual size_t getMaxChannelCount() const { return 1; }
cannam@0 178
cannam@0 179 struct OutputDescriptor
cannam@0 180 {
cannam@0 181 /**
cannam@0 182 * The name of the output, in computer-usable form. Should be
cannam@0 183 * reasonably short and without whitespace or punctuation.
cannam@0 184 */
cannam@0 185 std::string name;
cannam@0 186
cannam@0 187 /**
cannam@0 188 * The human-readable name of the output.
cannam@0 189 */
cannam@0 190 std::string description;
cannam@0 191
cannam@0 192 /**
cannam@0 193 * The unit of the output, in human-readable form.
cannam@0 194 */
cannam@0 195 std::string unit;
cannam@0 196
cannam@0 197 /**
cannam@0 198 * True if the output has the same number of values per result
cannam@0 199 * for every output result. Outputs for which this is false
cannam@0 200 * are unlikely to be very useful in a general-purpose host.
cannam@0 201 */
cannam@0 202 bool hasFixedValueCount;
cannam@0 203
cannam@0 204 /**
cannam@0 205 * The number of values per result of the output. Undefined
cannam@0 206 * if hasFixedValueCount is false. If this is zero, the output
cannam@0 207 * is point data (i.e. only the time of each output is of
cannam@0 208 * interest, the value list will be empty).
cannam@0 209 *
cannam@0 210 * Note that this gives the number of values of a single
cannam@0 211 * output result, not of the output stream (which has one more
cannam@0 212 * dimension: time).
cannam@0 213 */
cannam@0 214 size_t valueCount;
cannam@0 215
cannam@0 216 /**
cannam@0 217 * The names of each of the values, if appropriate. This is
cannam@0 218 * always optional.
cannam@0 219 */
cannam@0 220 std::vector<std::string> valueNames;
cannam@0 221
cannam@0 222 /**
cannam@0 223 * True if the results in the output have a fixed numeric
cannam@0 224 * range (minimum and maximum values). Undefined if
cannam@0 225 * valueCount is zero.
cannam@0 226 */
cannam@0 227 bool hasKnownExtents;
cannam@0 228
cannam@0 229 /**
cannam@0 230 * Minimum value of the results in the output. Undefined if
cannam@0 231 * hasKnownExtents is false or valueCount is zero.
cannam@0 232 */
cannam@0 233 float minValue;
cannam@0 234
cannam@0 235 /**
cannam@0 236 * Maximum value of the results in the output. Undefined if
cannam@0 237 * hasKnownExtents is false or valueCount is zero.
cannam@0 238 */
cannam@0 239 float maxValue;
cannam@0 240
cannam@0 241 /**
cannam@0 242 * True if the output values are quantized to a particular
cannam@0 243 * resolution. Undefined if valueCount is zero.
cannam@0 244 */
cannam@0 245 bool isQuantized;
cannam@0 246
cannam@0 247 /**
cannam@0 248 * Quantization resolution of the output values (e.g. 1.0 if
cannam@0 249 * they are all integers). Undefined if isQuantized is false
cannam@0 250 * or valueCount is zero.
cannam@0 251 */
cannam@0 252 float quantizeStep;
cannam@0 253
cannam@0 254 enum SampleType {
cannam@0 255
cannam@0 256 /// Results from each process() align with that call's block start
cannam@0 257 OneSamplePerStep,
cannam@0 258
cannam@0 259 /// Results are evenly spaced in time (sampleRate specified below)
cannam@0 260 FixedSampleRate,
cannam@0 261
cannam@0 262 /// Results are unevenly spaced and have individual timestamps
cannam@0 263 VariableSampleRate
cannam@0 264 };
cannam@0 265
cannam@0 266 /**
cannam@0 267 * Positioning in time of the output results.
cannam@0 268 */
cannam@0 269 SampleType sampleType;
cannam@0 270
cannam@0 271 /**
cannam@0 272 * Sample rate of the output results. Undefined if sampleType
cannam@0 273 * is OneSamplePerStep.
cannam@0 274 *
cannam@0 275 * If sampleType is VariableSampleRate and this value is
cannam@0 276 * non-zero, then it may be used to calculate a resolution for
cannam@0 277 * the output (i.e. the "duration" of each value, in time).
cannam@0 278 * It's recommended to set this to zero if that behaviour is
cannam@0 279 * not desired.
cannam@0 280 */
cannam@0 281 float sampleRate;
cannam@0 282 };
cannam@0 283
cannam@0 284 typedef std::vector<OutputDescriptor> OutputList;
cannam@0 285
cannam@0 286 /**
cannam@0 287 * Get the outputs of this plugin. An output's index in this list
cannam@0 288 * is used as its numeric index when looking it up in the
cannam@0 289 * FeatureSet returned from the process() call.
cannam@0 290 */
cannam@0 291 virtual OutputList getOutputDescriptors() const = 0;
cannam@0 292
cannam@0 293 struct Feature
cannam@0 294 {
cannam@0 295 /**
cannam@0 296 * True if an output feature has its own timestamp. This is
cannam@0 297 * mandatory if the output has VariableSampleRate, and is
cannam@0 298 * likely to be disregarded otherwise.
cannam@0 299 */
cannam@0 300 bool hasTimestamp;
cannam@0 301
cannam@0 302 /**
cannam@0 303 * Timestamp of the output feature. This is mandatory if the
cannam@0 304 * output has VariableSampleRate, and is likely to be
cannam@0 305 * disregarded otherwise. Undefined if hasTimestamp is false.
cannam@0 306 */
cannam@0 307 RealTime timestamp;
cannam@0 308
cannam@0 309 /**
cannam@0 310 * Results for a single sample of this feature. If the output
cannam@0 311 * hasFixedValueCount, there must be the same number of values
cannam@0 312 * as the output's valueCount count.
cannam@0 313 */
cannam@0 314 std::vector<float> values;
cannam@0 315
cannam@0 316 /**
cannam@0 317 * Label for the sample of this feature.
cannam@0 318 */
cannam@0 319 std::string label;
cannam@0 320 };
cannam@0 321
cannam@0 322 typedef std::vector<Feature> FeatureList;
cannam@0 323 typedef std::map<int, FeatureList> FeatureSet; // key is output no
cannam@0 324
cannam@0 325 /**
cannam@0 326 * Process a single block of input data.
cannam@0 327 *
cannam@0 328 * If the plugin's inputDomain is TimeDomain, inputBuffers will
cannam@0 329 * point to one array of floats per input channel, and each of
cannam@0 330 * these arrays will contain blockSize consecutive audio samples
cannam@0 331 * (the host will zero-pad as necessary).
cannam@0 332 *
cannam@0 333 * If the plugin's inputDomain is FrequencyDomain, inputBuffers
cannam@0 334 * will point to one array of floats per input channel, and each
cannam@0 335 * of these arrays will contain blockSize/2 consecutive pairs of
cannam@0 336 * real and imaginary component floats corresponding to bins
cannam@0 337 * 0..(blockSize/2-1) of the FFT output.
cannam@0 338 *
cannam@0 339 * The timestamp is the real time in seconds of the start of the
cannam@0 340 * supplied block of samples.
cannam@0 341 *
cannam@0 342 * Return any features that have become available after this
cannam@0 343 * process call. (These do not necessarily have to fall within
cannam@0 344 * the process block, except for OneSamplePerStep outputs.)
cannam@0 345 */
cannam@0 346 virtual FeatureSet process(float **inputBuffers,
cannam@0 347 RealTime timestamp) = 0;
cannam@0 348
cannam@0 349 /**
cannam@0 350 * After all blocks have been processed, calculate and return any
cannam@0 351 * remaining features derived from the complete input.
cannam@0 352 */
cannam@0 353 virtual FeatureSet getRemainingFeatures() = 0;
cannam@0 354
cannam@0 355 virtual std::string getType() const { return "Feature Extraction Plugin"; }
cannam@0 356
cannam@0 357 protected:
cannam@0 358 Plugin(float inputSampleRate) :
cannam@0 359 m_inputSampleRate(inputSampleRate) { }
cannam@0 360
cannam@0 361 float m_inputSampleRate;
cannam@0 362 };
cannam@0 363
cannam@0 364 }
cannam@0 365
cannam@0 366 #endif
cannam@0 367
cannam@0 368
cannam@0 369