SpectralCentroid.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Vamp
00005 
00006     An API for audio analysis and feature extraction plugins.
00007 
00008     Centre for Digital Music, Queen Mary, University of London.
00009     Copyright 2006 Chris Cannam.
00010   
00011     Permission is hereby granted, free of charge, to any person
00012     obtaining a copy of this software and associated documentation
00013     files (the "Software"), to deal in the Software without
00014     restriction, including without limitation the rights to use, copy,
00015     modify, merge, publish, distribute, sublicense, and/or sell copies
00016     of the Software, and to permit persons to whom the Software is
00017     furnished to do so, subject to the following conditions:
00018 
00019     The above copyright notice and this permission notice shall be
00020     included in all copies or substantial portions of the Software.
00021 
00022     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00023     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00024     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00025     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
00026     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00027     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00028     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00029 
00030     Except as contained in this notice, the names of the Centre for
00031     Digital Music; Queen Mary, University of London; and Chris Cannam
00032     shall not be used in advertising or otherwise to promote the sale,
00033     use or other dealings in this Software without prior written
00034     authorization.
00035 */
00036 
00037 #include "SpectralCentroid.h"
00038 
00039 using std::string;
00040 using std::vector;
00041 using std::cerr;
00042 using std::endl;
00043 
00044 #include <math.h>
00045 
00046 #ifdef __SUNPRO_CC
00047 #include <ieeefp.h>
00048 #define isinf(x) (!finite(x))
00049 #endif
00050 
00051 #ifdef WIN32
00052 #define isnan(x) false
00053 #define isinf(x) false
00054 #endif
00055 
00056 SpectralCentroid::SpectralCentroid(float inputSampleRate) :
00057     Plugin(inputSampleRate),
00058     m_stepSize(0),
00059     m_blockSize(0)
00060 {
00061 }
00062 
00063 SpectralCentroid::~SpectralCentroid()
00064 {
00065 }
00066 
00067 string
00068 SpectralCentroid::getIdentifier() const
00069 {
00070     return "spectralcentroid";
00071 }
00072 
00073 string
00074 SpectralCentroid::getName() const
00075 {
00076     return "Spectral Centroid";
00077 }
00078 
00079 string
00080 SpectralCentroid::getDescription() const
00081 {
00082     return "Calculate the centroid frequency of the spectrum of the input signal";
00083 }
00084 
00085 string
00086 SpectralCentroid::getMaker() const
00087 {
00088     return "Vamp SDK Example Plugins";
00089 }
00090 
00091 int
00092 SpectralCentroid::getPluginVersion() const
00093 {
00094     return 2;
00095 }
00096 
00097 string
00098 SpectralCentroid::getCopyright() const
00099 {
00100     return "Freely redistributable (BSD license)";
00101 }
00102 
00103 bool
00104 SpectralCentroid::initialise(size_t channels, size_t stepSize, size_t blockSize)
00105 {
00106     if (channels < getMinChannelCount() ||
00107         channels > getMaxChannelCount()) return false;
00108 
00109     m_stepSize = stepSize;
00110     m_blockSize = blockSize;
00111 
00112     return true;
00113 }
00114 
00115 void
00116 SpectralCentroid::reset()
00117 {
00118 }
00119 
00120 SpectralCentroid::OutputList
00121 SpectralCentroid::getOutputDescriptors() const
00122 {
00123     OutputList list;
00124 
00125     OutputDescriptor d;
00126     d.identifier = "logcentroid";
00127     d.name = "Log Frequency Centroid";
00128     d.description = "Centroid of the log weighted frequency spectrum";
00129     d.unit = "Hz";
00130     d.hasFixedBinCount = true;
00131     d.binCount = 1;
00132     d.hasKnownExtents = false;
00133     d.isQuantized = false;
00134     d.sampleType = OutputDescriptor::OneSamplePerStep;
00135     list.push_back(d);
00136 
00137     d.identifier = "linearcentroid";
00138     d.name = "Linear Frequency Centroid";
00139     d.description = "Centroid of the linear frequency spectrum";
00140     list.push_back(d);
00141 
00142     return list;
00143 }
00144 
00145 SpectralCentroid::FeatureSet
00146 SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime)
00147 {
00148     if (m_stepSize == 0) {
00149         cerr << "ERROR: SpectralCentroid::process: "
00150              << "SpectralCentroid has not been initialised"
00151              << endl;
00152         return FeatureSet();
00153     }
00154 
00155     double numLin = 0.0, numLog = 0.0, denom = 0.0;
00156 
00157     for (size_t i = 1; i <= m_blockSize/2; ++i) {
00158         double freq = (double(i) * m_inputSampleRate) / m_blockSize;
00159         double real = inputBuffers[0][i*2];
00160         double imag = inputBuffers[0][i*2 + 1];
00161         double scalemag = sqrt(real * real + imag * imag) / (m_blockSize/2);
00162         numLin += freq * scalemag;
00163         numLog += log10f(freq) * scalemag;
00164         denom += scalemag;
00165     }
00166 
00167     FeatureSet returnFeatures;
00168 
00169     if (denom != 0.0) {
00170         float centroidLin = float(numLin / denom);
00171         float centroidLog = powf(10, float(numLog / denom));
00172 
00173         Feature feature;
00174         feature.hasTimestamp = false;
00175 
00176         if (!isnan(centroidLog) && !isinf(centroidLog)) {
00177             feature.values.push_back(centroidLog);
00178         }
00179         returnFeatures[0].push_back(feature);
00180 
00181         feature.values.clear();
00182         if (!isnan(centroidLin) && !isinf(centroidLin)) {
00183             feature.values.push_back(centroidLin);
00184         }
00185         returnFeatures[1].push_back(feature);
00186     }
00187 
00188     return returnFeatures;
00189 }
00190 
00191 SpectralCentroid::FeatureSet
00192 SpectralCentroid::getRemainingFeatures()
00193 {
00194     return FeatureSet();
00195 }
00196