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