annotate osx/include/vamp-sdk/Plugin.h @ 118:a8541380d3e0

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