annotate plugin/FeatureExtractionPlugin.h @ 14:b101cc2ae1ab

* Introduce potentially-separate read and write ring buffers, so we can swap in a new set when something changes -- thus allowing us to respond quickly when something changes during playback, without losing the long buffers * Some fixes for display & editing
author Chris Cannam
date Fri, 27 Jan 2006 18:04:07 +0000
parents d86891498eef
children a7ed14263fe4
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #ifndef _FEATURE_EXTRACTION_PLUGIN_H_
Chris@0 11 #define _FEATURE_EXTRACTION_PLUGIN_H_
Chris@0 12
Chris@0 13 /**
Chris@0 14 * A base class for feature extraction plugins.
Chris@0 15 */
Chris@0 16
Chris@0 17 #include <string>
Chris@0 18 #include <vector>
Chris@0 19 #include <map>
Chris@0 20
Chris@0 21 #include "base/RealTime.h"
Chris@0 22
Chris@0 23 /**
Chris@0 24 * FeatureExtractionPlugin is a base class for plugin instance classes
Chris@0 25 * that provide feature extraction from audio or related data.
Chris@0 26 *
Chris@0 27 * In most cases, the input will be audio and the output will be a
Chris@0 28 * stream of derived data at a lower sampling resolution than the
Chris@0 29 * input.
Chris@0 30 */
Chris@0 31
Chris@0 32 class FeatureExtractionPlugin
Chris@0 33 {
Chris@0 34 public:
Chris@0 35 /**
Chris@0 36 * Initialise a plugin to prepare it for use with the given number
Chris@0 37 * of input channels, step size (window increment, in sample
Chris@0 38 * frames) and block size (window size, in sample frames).
Chris@0 39 *
Chris@0 40 * The input sample rate should have been already specified at
Chris@0 41 * construction time.
Chris@0 42 *
Chris@0 43 * Return true for successful initialisation, false if the number
Chris@0 44 * of input channels, step size and/or block size cannot be
Chris@0 45 * supported.
Chris@0 46 */
Chris@0 47 virtual bool initialise(size_t inputChannels,
Chris@0 48 size_t stepSize,
Chris@0 49 size_t blockSize) = 0;
Chris@0 50
Chris@0 51 /**
Chris@0 52 * Reset the plugin after use, to prepare it for another clean
Chris@0 53 * run. Not called for the first initialisation (i.e. initialise
Chris@0 54 * must also do a reset).
Chris@0 55 */
Chris@0 56 virtual void reset() = 0;
Chris@0 57
Chris@0 58 /**
Chris@0 59 * Get the computer-usable name of the plugin. This should be
Chris@0 60 * reasonably short and contain no whitespace or punctuation
Chris@0 61 * characters.
Chris@0 62 */
Chris@0 63 virtual std::string getName() const = 0;
Chris@0 64
Chris@0 65 /**
Chris@0 66 * Get a human-readable description of the plugin. This should be
Chris@0 67 * self-contained, as it may be shown to the user in isolation
Chris@0 68 * without also showing the plugin's "name".
Chris@0 69 */
Chris@0 70 virtual std::string getDescription() const = 0;
Chris@0 71
Chris@0 72 /**
Chris@0 73 * Get the name of the author or vendor of the plugin in
Chris@0 74 * human-readable form.
Chris@0 75 */
Chris@0 76 virtual std::string getMaker() const = 0;
Chris@0 77
Chris@0 78 /**
Chris@0 79 * Get the version number of the plugin.
Chris@0 80 */
Chris@0 81 virtual int getPluginVersion() const = 0;
Chris@0 82
Chris@0 83 /**
Chris@0 84 * Get the copyright statement or licensing summary of the plugin.
Chris@0 85 */
Chris@0 86 virtual std::string getCopyright() const = 0;
Chris@0 87
Chris@0 88 /**
Chris@0 89 * Get the preferred step size (window increment -- the distance
Chris@0 90 * in sample frames between the start frames of consecutive blocks
Chris@0 91 * passed to the process() function) for the plugin. This should
Chris@0 92 * be called before initialise().
Chris@0 93 */
Chris@0 94 virtual size_t getPreferredStepSize() const = 0;
Chris@0 95
Chris@0 96 /**
Chris@0 97 * Get the preferred block size (window size -- the number of
Chris@0 98 * sample frames passed in each block to the process() function).
Chris@0 99 * This should be called before initialise().
Chris@0 100 */
Chris@0 101 virtual size_t getPreferredBlockSize() const { return getPreferredStepSize(); }
Chris@0 102
Chris@0 103 /**
Chris@0 104 * Get the minimum supported number of input channels.
Chris@0 105 */
Chris@0 106 virtual size_t getMinChannelCount() const { return 1; }
Chris@0 107
Chris@0 108 /**
Chris@0 109 * Get the maximum supported number of input channels.
Chris@0 110 */
Chris@0 111 virtual size_t getMaxChannelCount() const { return 1; }
Chris@0 112
Chris@0 113
Chris@0 114 struct OutputDescriptor
Chris@0 115 {
Chris@0 116 /**
Chris@0 117 * The name of the output, in computer-usable form. Should be
Chris@0 118 * reasonably short and without whitespace or punctuation.
Chris@0 119 */
Chris@0 120 std::string name;
Chris@0 121
Chris@0 122 /**
Chris@0 123 * The human-readable name of the output.
Chris@0 124 */
Chris@0 125 std::string description;
Chris@0 126
Chris@0 127 /**
Chris@0 128 * The unit of the output, in human-readable form.
Chris@0 129 */
Chris@0 130 std::string unit;
Chris@0 131
Chris@0 132 /**
Chris@0 133 * True if the output has the same number of values per result
Chris@0 134 * for every output result. Outputs for which this is false
Chris@0 135 * are unlikely to be very useful in a general-purpose host.
Chris@0 136 */
Chris@0 137 bool hasFixedValueCount;
Chris@0 138
Chris@0 139 /**
Chris@0 140 * The number of values per result of the output. Undefined
Chris@0 141 * if hasFixedValueCount is false. If this is zero, the output
Chris@0 142 * is point data (i.e. only the time of each output is of
Chris@0 143 * interest, the value list will be empty).
Chris@0 144 *
Chris@0 145 * Note that this gives the number of values of a single
Chris@0 146 * output result, not of the output stream (which has one more
Chris@0 147 * dimension: time).
Chris@0 148 */
Chris@0 149 size_t valueCount;
Chris@0 150
Chris@0 151 /**
Chris@0 152 * True if the results in the output have a fixed numeric
Chris@0 153 * range (minimum and maximum values). Undefined if
Chris@0 154 * valueCount is zero.
Chris@0 155 */
Chris@0 156 bool hasKnownExtents;
Chris@0 157
Chris@0 158 /**
Chris@0 159 * Minimum value of the results in the output. Undefined if
Chris@0 160 * hasKnownExtents is false or valueCount is zero.
Chris@0 161 */
Chris@0 162 float minValue;
Chris@0 163
Chris@0 164 /**
Chris@0 165 * Maximum value of the results in the output. Undefined if
Chris@0 166 * hasKnownExtents is false or valueCount is zero.
Chris@0 167 */
Chris@0 168 float maxValue;
Chris@0 169
Chris@0 170 /**
Chris@0 171 * True if the output values are quantized to a particular
Chris@0 172 * resolution. Undefined if valueCount is zero.
Chris@0 173 */
Chris@0 174 bool isQuantized;
Chris@0 175
Chris@0 176 /**
Chris@0 177 * Quantization resolution of the output values (e.g. 1.0 if
Chris@0 178 * they are all integers). Undefined if isQuantized is false
Chris@0 179 * or valueCount is zero.
Chris@0 180 */
Chris@0 181 float quantizeStep;
Chris@0 182
Chris@0 183 enum SampleType {
Chris@0 184
Chris@0 185 /// Results from each process() align with that call's block start
Chris@0 186 OneSamplePerStep,
Chris@0 187
Chris@0 188 /// Results are evenly spaced in time (sampleRate specified below)
Chris@0 189 FixedSampleRate,
Chris@0 190
Chris@0 191 /// Results are unevenly spaced and have individual timestamps
Chris@0 192 VariableSampleRate
Chris@0 193 };
Chris@0 194
Chris@0 195 /**
Chris@0 196 * Positioning in time of the output results.
Chris@0 197 */
Chris@0 198 SampleType sampleType;
Chris@0 199
Chris@0 200 /**
Chris@0 201 * Sample rate of the output results. Undefined if sampleType
Chris@0 202 * is OneSamplePerStep.
Chris@0 203 *
Chris@0 204 * If sampleType is VariableSampleRate and this value is
Chris@0 205 * non-zero, then it may be used to calculate a resolution for
Chris@0 206 * the output (i.e. the "duration" of each value, in time).
Chris@0 207 * It's recommended to set this to zero if that behaviour is
Chris@0 208 * not desired.
Chris@0 209 */
Chris@0 210 float sampleRate;
Chris@0 211 };
Chris@0 212
Chris@0 213 typedef std::vector<OutputDescriptor> OutputList;
Chris@0 214
Chris@0 215 /**
Chris@0 216 * Get the outputs of this plugin. An output's index in this list
Chris@0 217 * is used as its numeric index when looking it up in the
Chris@0 218 * FeatureSet returned from the process() call.
Chris@0 219 */
Chris@0 220 virtual OutputList getOutputDescriptors() const = 0;
Chris@0 221
Chris@0 222
Chris@0 223 struct ParameterDescriptor
Chris@0 224 {
Chris@0 225 /**
Chris@0 226 * The name of the parameter, in computer-usable form. Should
Chris@0 227 * be reasonably short and without whitespace or punctuation.
Chris@0 228 */
Chris@0 229 std::string name;
Chris@0 230
Chris@0 231 /**
Chris@0 232 * The human-readable name of the parameter.
Chris@0 233 */
Chris@0 234 std::string description;
Chris@0 235
Chris@0 236 /**
Chris@0 237 * The unit of the parameter, in human-readable form.
Chris@0 238 */
Chris@0 239 std::string unit;
Chris@0 240
Chris@0 241 /**
Chris@0 242 * The minimum value of the parameter.
Chris@0 243 */
Chris@0 244 float minValue;
Chris@0 245
Chris@0 246 /**
Chris@0 247 * The maximum value of the parameter.
Chris@0 248 */
Chris@0 249 float maxValue;
Chris@0 250
Chris@0 251 /**
Chris@0 252 * The default value of the parameter.
Chris@0 253 */
Chris@0 254 float defaultValue;
Chris@0 255
Chris@0 256 /**
Chris@0 257 * True if the parameter values are quantized to a particular
Chris@0 258 * resolution.
Chris@0 259 */
Chris@0 260 bool isQuantized;
Chris@0 261
Chris@0 262 /**
Chris@0 263 * Quantization resolution of the parameter values (e.g. 1.0
Chris@0 264 * if they are all integers). Undefined if isQuantized is
Chris@0 265 * false.
Chris@0 266 */
Chris@0 267 float quantizeStep;
Chris@0 268 };
Chris@0 269
Chris@0 270 typedef std::vector<ParameterDescriptor> ParameterList;
Chris@0 271
Chris@0 272 /**
Chris@0 273 * Get the controllable parameters of this plugin.
Chris@0 274 */
Chris@0 275 virtual ParameterList getParameterDescriptors() const {
Chris@0 276 return ParameterList();
Chris@0 277 }
Chris@0 278
Chris@0 279 /**
Chris@0 280 * Get the value of a named parameter. The argument is the name
Chris@0 281 * field from that parameter's descriptor.
Chris@0 282 */
Chris@0 283 virtual float getParameter(std::string) const { return 0.0; }
Chris@0 284
Chris@0 285 /**
Chris@0 286 * Set a named parameter. The first argument is the name field
Chris@0 287 * from that parameter's descriptor.
Chris@0 288 */
Chris@0 289 virtual void setParameter(std::string, float) { }
Chris@0 290
Chris@0 291 struct Feature
Chris@0 292 {
Chris@0 293 /**
Chris@0 294 * True if an output feature has its own timestamp. This is
Chris@0 295 * mandatory if the output has VariableSampleRate, and is
Chris@0 296 * likely to be disregarded otherwise.
Chris@0 297 */
Chris@0 298 bool hasTimestamp;
Chris@0 299
Chris@0 300 /**
Chris@0 301 * Timestamp of the output feature. This is mandatory if the
Chris@0 302 * output has VariableSampleRate, and is likely to be
Chris@0 303 * disregarded otherwise. Undefined if hasTimestamp is false.
Chris@0 304 */
Chris@0 305 RealTime timestamp;
Chris@0 306
Chris@0 307 /**
Chris@0 308 * Results for a single sample of this feature. If the output
Chris@0 309 * hasFixedValueCount, there must be the same number of values
Chris@0 310 * as the output's valueCount count.
Chris@0 311 */
Chris@0 312 std::vector<float> values;
Chris@0 313
Chris@0 314 /**
Chris@0 315 * Label for the sample of this feature.
Chris@0 316 */
Chris@0 317 std::string label;
Chris@0 318 };
Chris@0 319
Chris@0 320 typedef std::vector<Feature> FeatureList;
Chris@0 321 typedef std::map<int, FeatureList> FeatureSet; // key is output no
Chris@0 322
Chris@0 323 /**
Chris@0 324 * Process a single block of input data. inputBuffers points to
Chris@0 325 * one array of floats per input channel, and each of those arrays
Chris@0 326 * contains the blockSize number of samples (the host will
Chris@0 327 * zero-pad as necessary). The timestamp is the real time in
Chris@0 328 * seconds of the start of the supplied block of samples.
Chris@0 329 *
Chris@0 330 * Return any features that have become available after this
Chris@0 331 * process call. (These do not necessarily have to fall within
Chris@0 332 * the process block, except for OneSamplePerStep outputs.)
Chris@0 333 */
Chris@0 334 virtual FeatureSet process(float **inputBuffers,
Chris@0 335 RealTime timestamp) = 0;
Chris@0 336
Chris@0 337 /**
Chris@0 338 * After all blocks have been processed, calculate and return any
Chris@0 339 * remaining features derived from the complete input.
Chris@0 340 */
Chris@0 341 virtual FeatureSet getRemainingFeatures() = 0;
Chris@0 342
Chris@0 343 protected:
Chris@0 344 FeatureExtractionPlugin(float inputSampleRate) :
Chris@0 345 m_inputSampleRate(inputSampleRate) { }
Chris@0 346
Chris@0 347 float m_inputSampleRate;
Chris@0 348 };
Chris@0 349
Chris@0 350 #endif
Chris@0 351
Chris@0 352
Chris@0 353