Chris@0: /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@2: Chris Cannam, Queen Mary University of London, 2005-2006 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@0: #ifndef _FEATURE_EXTRACTION_PLUGIN_H_ Chris@0: #define _FEATURE_EXTRACTION_PLUGIN_H_ Chris@0: Chris@0: /** Chris@0: * A base class for feature extraction plugins. Chris@0: */ Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include "base/RealTime.h" Chris@0: Chris@0: /** Chris@0: * FeatureExtractionPlugin is a base class for plugin instance classes Chris@0: * that provide feature extraction from audio or related data. Chris@0: * Chris@0: * In most cases, the input will be audio and the output will be a Chris@0: * stream of derived data at a lower sampling resolution than the Chris@0: * input. Chris@0: */ Chris@0: Chris@0: class FeatureExtractionPlugin Chris@0: { Chris@0: public: Chris@0: /** Chris@0: * Initialise a plugin to prepare it for use with the given number Chris@0: * of input channels, step size (window increment, in sample Chris@0: * frames) and block size (window size, in sample frames). Chris@0: * Chris@0: * The input sample rate should have been already specified at Chris@0: * construction time. Chris@0: * Chris@0: * Return true for successful initialisation, false if the number Chris@0: * of input channels, step size and/or block size cannot be Chris@0: * supported. Chris@0: */ Chris@0: virtual bool initialise(size_t inputChannels, Chris@0: size_t stepSize, Chris@0: size_t blockSize) = 0; Chris@0: Chris@0: /** Chris@0: * Reset the plugin after use, to prepare it for another clean Chris@0: * run. Not called for the first initialisation (i.e. initialise Chris@0: * must also do a reset). Chris@0: */ Chris@0: virtual void reset() = 0; Chris@0: Chris@0: /** Chris@0: * Get the computer-usable name of the plugin. This should be Chris@0: * reasonably short and contain no whitespace or punctuation Chris@0: * characters. Chris@0: */ Chris@0: virtual std::string getName() const = 0; Chris@0: Chris@0: /** Chris@0: * Get a human-readable description of the plugin. This should be Chris@0: * self-contained, as it may be shown to the user in isolation Chris@0: * without also showing the plugin's "name". Chris@0: */ Chris@0: virtual std::string getDescription() const = 0; Chris@0: Chris@0: /** Chris@0: * Get the name of the author or vendor of the plugin in Chris@0: * human-readable form. Chris@0: */ Chris@0: virtual std::string getMaker() const = 0; Chris@0: Chris@0: /** Chris@0: * Get the version number of the plugin. Chris@0: */ Chris@0: virtual int getPluginVersion() const = 0; Chris@0: Chris@0: /** Chris@0: * Get the copyright statement or licensing summary of the plugin. Chris@0: */ Chris@0: virtual std::string getCopyright() const = 0; Chris@0: Chris@0: /** Chris@0: * Get the preferred step size (window increment -- the distance Chris@0: * in sample frames between the start frames of consecutive blocks Chris@0: * passed to the process() function) for the plugin. This should Chris@0: * be called before initialise(). Chris@0: */ Chris@0: virtual size_t getPreferredStepSize() const = 0; Chris@0: Chris@0: /** Chris@0: * Get the preferred block size (window size -- the number of Chris@0: * sample frames passed in each block to the process() function). Chris@0: * This should be called before initialise(). Chris@0: */ Chris@0: virtual size_t getPreferredBlockSize() const { return getPreferredStepSize(); } Chris@0: Chris@0: /** Chris@0: * Get the minimum supported number of input channels. Chris@0: */ Chris@0: virtual size_t getMinChannelCount() const { return 1; } Chris@0: Chris@0: /** Chris@0: * Get the maximum supported number of input channels. Chris@0: */ Chris@0: virtual size_t getMaxChannelCount() const { return 1; } Chris@0: Chris@0: Chris@0: struct OutputDescriptor Chris@0: { Chris@0: /** Chris@0: * The name of the output, in computer-usable form. Should be Chris@0: * reasonably short and without whitespace or punctuation. Chris@0: */ Chris@0: std::string name; Chris@0: Chris@0: /** Chris@0: * The human-readable name of the output. Chris@0: */ Chris@0: std::string description; Chris@0: Chris@0: /** Chris@0: * The unit of the output, in human-readable form. Chris@0: */ Chris@0: std::string unit; Chris@0: Chris@0: /** Chris@0: * True if the output has the same number of values per result Chris@0: * for every output result. Outputs for which this is false Chris@0: * are unlikely to be very useful in a general-purpose host. Chris@0: */ Chris@0: bool hasFixedValueCount; Chris@0: Chris@0: /** Chris@0: * The number of values per result of the output. Undefined Chris@0: * if hasFixedValueCount is false. If this is zero, the output Chris@0: * is point data (i.e. only the time of each output is of Chris@0: * interest, the value list will be empty). Chris@0: * Chris@0: * Note that this gives the number of values of a single Chris@0: * output result, not of the output stream (which has one more Chris@0: * dimension: time). Chris@0: */ Chris@0: size_t valueCount; Chris@0: Chris@0: /** Chris@19: * The names of each of the values, if appropriate. This is Chris@19: * always optional. Chris@19: */ Chris@19: std::vector valueNames; Chris@19: Chris@19: /** Chris@0: * True if the results in the output have a fixed numeric Chris@0: * range (minimum and maximum values). Undefined if Chris@0: * valueCount is zero. Chris@0: */ Chris@0: bool hasKnownExtents; Chris@0: Chris@0: /** Chris@0: * Minimum value of the results in the output. Undefined if Chris@0: * hasKnownExtents is false or valueCount is zero. Chris@0: */ Chris@0: float minValue; Chris@0: Chris@0: /** Chris@0: * Maximum value of the results in the output. Undefined if Chris@0: * hasKnownExtents is false or valueCount is zero. Chris@0: */ Chris@0: float maxValue; Chris@0: Chris@0: /** Chris@0: * True if the output values are quantized to a particular Chris@0: * resolution. Undefined if valueCount is zero. Chris@0: */ Chris@0: bool isQuantized; Chris@0: Chris@0: /** Chris@0: * Quantization resolution of the output values (e.g. 1.0 if Chris@0: * they are all integers). Undefined if isQuantized is false Chris@0: * or valueCount is zero. Chris@0: */ Chris@0: float quantizeStep; Chris@0: Chris@0: enum SampleType { Chris@0: Chris@0: /// Results from each process() align with that call's block start Chris@0: OneSamplePerStep, Chris@0: Chris@0: /// Results are evenly spaced in time (sampleRate specified below) Chris@0: FixedSampleRate, Chris@0: Chris@0: /// Results are unevenly spaced and have individual timestamps Chris@0: VariableSampleRate Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Positioning in time of the output results. Chris@0: */ Chris@0: SampleType sampleType; Chris@0: Chris@0: /** Chris@0: * Sample rate of the output results. Undefined if sampleType Chris@0: * is OneSamplePerStep. Chris@0: * Chris@0: * If sampleType is VariableSampleRate and this value is Chris@0: * non-zero, then it may be used to calculate a resolution for Chris@0: * the output (i.e. the "duration" of each value, in time). Chris@0: * It's recommended to set this to zero if that behaviour is Chris@0: * not desired. Chris@0: */ Chris@0: float sampleRate; Chris@0: }; Chris@0: Chris@0: typedef std::vector OutputList; Chris@0: Chris@0: /** Chris@0: * Get the outputs of this plugin. An output's index in this list Chris@0: * is used as its numeric index when looking it up in the Chris@0: * FeatureSet returned from the process() call. Chris@0: */ Chris@0: virtual OutputList getOutputDescriptors() const = 0; Chris@0: Chris@0: Chris@0: struct ParameterDescriptor Chris@0: { Chris@0: /** Chris@0: * The name of the parameter, in computer-usable form. Should Chris@0: * be reasonably short and without whitespace or punctuation. Chris@0: */ Chris@0: std::string name; Chris@0: Chris@0: /** Chris@0: * The human-readable name of the parameter. Chris@0: */ Chris@0: std::string description; Chris@0: Chris@0: /** Chris@0: * The unit of the parameter, in human-readable form. Chris@0: */ Chris@0: std::string unit; Chris@0: Chris@0: /** Chris@0: * The minimum value of the parameter. Chris@0: */ Chris@0: float minValue; Chris@0: Chris@0: /** Chris@0: * The maximum value of the parameter. Chris@0: */ Chris@0: float maxValue; Chris@0: Chris@0: /** Chris@0: * The default value of the parameter. Chris@0: */ Chris@0: float defaultValue; Chris@0: Chris@0: /** Chris@0: * True if the parameter values are quantized to a particular Chris@0: * resolution. Chris@0: */ Chris@0: bool isQuantized; Chris@0: Chris@0: /** Chris@0: * Quantization resolution of the parameter values (e.g. 1.0 Chris@0: * if they are all integers). Undefined if isQuantized is Chris@0: * false. Chris@0: */ Chris@0: float quantizeStep; Chris@0: }; Chris@0: Chris@0: typedef std::vector ParameterList; Chris@0: Chris@0: /** Chris@0: * Get the controllable parameters of this plugin. Chris@0: */ Chris@0: virtual ParameterList getParameterDescriptors() const { Chris@0: return ParameterList(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the value of a named parameter. The argument is the name Chris@0: * field from that parameter's descriptor. Chris@0: */ Chris@0: virtual float getParameter(std::string) const { return 0.0; } Chris@0: Chris@0: /** Chris@0: * Set a named parameter. The first argument is the name field Chris@0: * from that parameter's descriptor. Chris@0: */ Chris@0: virtual void setParameter(std::string, float) { } Chris@0: Chris@0: struct Feature Chris@0: { Chris@0: /** Chris@0: * True if an output feature has its own timestamp. This is Chris@0: * mandatory if the output has VariableSampleRate, and is Chris@0: * likely to be disregarded otherwise. Chris@0: */ Chris@0: bool hasTimestamp; Chris@0: Chris@0: /** Chris@0: * Timestamp of the output feature. This is mandatory if the Chris@0: * output has VariableSampleRate, and is likely to be Chris@0: * disregarded otherwise. Undefined if hasTimestamp is false. Chris@0: */ Chris@0: RealTime timestamp; Chris@0: Chris@0: /** Chris@0: * Results for a single sample of this feature. If the output Chris@0: * hasFixedValueCount, there must be the same number of values Chris@0: * as the output's valueCount count. Chris@0: */ Chris@0: std::vector values; Chris@0: Chris@0: /** Chris@0: * Label for the sample of this feature. Chris@0: */ Chris@0: std::string label; Chris@0: }; Chris@0: Chris@0: typedef std::vector FeatureList; Chris@0: typedef std::map FeatureSet; // key is output no Chris@0: Chris@0: /** Chris@0: * Process a single block of input data. inputBuffers points to Chris@0: * one array of floats per input channel, and each of those arrays Chris@0: * contains the blockSize number of samples (the host will Chris@0: * zero-pad as necessary). The timestamp is the real time in Chris@0: * seconds of the start of the supplied block of samples. Chris@0: * Chris@0: * Return any features that have become available after this Chris@0: * process call. (These do not necessarily have to fall within Chris@0: * the process block, except for OneSamplePerStep outputs.) Chris@0: */ Chris@0: virtual FeatureSet process(float **inputBuffers, Chris@0: RealTime timestamp) = 0; Chris@0: Chris@0: /** Chris@0: * After all blocks have been processed, calculate and return any Chris@0: * remaining features derived from the complete input. Chris@0: */ Chris@0: virtual FeatureSet getRemainingFeatures() = 0; Chris@0: Chris@0: protected: Chris@0: FeatureExtractionPlugin(float inputSampleRate) : Chris@0: m_inputSampleRate(inputSampleRate) { } Chris@0: Chris@0: float m_inputSampleRate; Chris@0: }; Chris@0: Chris@0: #endif Chris@0: Chris@0: Chris@0: