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 <cmath> 00045 00046 00047 SpectralCentroid::SpectralCentroid(float inputSampleRate) : 00048 Plugin(inputSampleRate), 00049 m_stepSize(0), 00050 m_blockSize(0) 00051 { 00052 } 00053 00054 SpectralCentroid::~SpectralCentroid() 00055 { 00056 } 00057 00058 string 00059 SpectralCentroid::getIdentifier() const 00060 { 00061 return "spectralcentroid"; 00062 } 00063 00064 string 00065 SpectralCentroid::getName() const 00066 { 00067 return "Spectral Centroid"; 00068 } 00069 00070 string 00071 SpectralCentroid::getDescription() const 00072 { 00073 return "Calculate the centroid frequency of the spectrum of the input signal"; 00074 } 00075 00076 string 00077 SpectralCentroid::getMaker() const 00078 { 00079 return "Vamp SDK Example Plugins"; 00080 } 00081 00082 int 00083 SpectralCentroid::getPluginVersion() const 00084 { 00085 return 2; 00086 } 00087 00088 string 00089 SpectralCentroid::getCopyright() const 00090 { 00091 return "Freely redistributable (BSD license)"; 00092 } 00093 00094 bool 00095 SpectralCentroid::initialise(size_t channels, size_t stepSize, size_t blockSize) 00096 { 00097 if (channels < getMinChannelCount() || 00098 channels > getMaxChannelCount()) return false; 00099 00100 m_stepSize = stepSize; 00101 m_blockSize = blockSize; 00102 00103 return true; 00104 } 00105 00106 void 00107 SpectralCentroid::reset() 00108 { 00109 } 00110 00111 SpectralCentroid::OutputList 00112 SpectralCentroid::getOutputDescriptors() const 00113 { 00114 OutputList list; 00115 00116 OutputDescriptor d; 00117 d.identifier = "logcentroid"; 00118 d.name = "Log Frequency Centroid"; 00119 d.description = "Centroid of the log weighted frequency spectrum"; 00120 d.unit = "Hz"; 00121 d.hasFixedBinCount = true; 00122 d.binCount = 1; 00123 d.hasKnownExtents = false; 00124 d.isQuantized = false; 00125 d.sampleType = OutputDescriptor::OneSamplePerStep; 00126 list.push_back(d); 00127 00128 d.identifier = "linearcentroid"; 00129 d.name = "Linear Frequency Centroid"; 00130 d.description = "Centroid of the linear frequency spectrum"; 00131 list.push_back(d); 00132 00133 return list; 00134 } 00135 00136 SpectralCentroid::FeatureSet 00137 SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime) 00138 { 00139 if (m_stepSize == 0) { 00140 cerr << "ERROR: SpectralCentroid::process: " 00141 << "SpectralCentroid has not been initialised" 00142 << endl; 00143 return FeatureSet(); 00144 } 00145 00146 double numLin = 0.0, numLog = 0.0, denom = 0.0; 00147 00148 for (size_t i = 1; i <= m_blockSize/2; ++i) { 00149 double freq = (double(i) * m_inputSampleRate) / m_blockSize; 00150 double real = inputBuffers[0][i*2]; 00151 double imag = inputBuffers[0][i*2 + 1]; 00152 double power = sqrt(real * real + imag * imag) / (m_blockSize/2); 00153 numLin += freq * power; 00154 numLog += log10f(freq) * power; 00155 denom += power; 00156 } 00157 00158 FeatureSet returnFeatures; 00159 00160 // std::cerr << "power " << denom << ", block size " << m_blockSize << std::endl; 00161 00162 if (denom != 0.0) { 00163 float centroidLin = float(numLin / denom); 00164 float centroidLog = powf(10, float(numLog / denom)); 00165 00166 Feature feature; 00167 feature.hasTimestamp = false; 00168 if (!std::isnan(centroidLog) && !std::isinf(centroidLog)) { 00169 feature.values.push_back(centroidLog); 00170 } 00171 returnFeatures[0].push_back(feature); 00172 00173 feature.values.clear(); 00174 if (!std::isnan(centroidLin) && !std::isinf(centroidLin)) { 00175 feature.values.push_back(centroidLin); 00176 } 00177 returnFeatures[1].push_back(feature); 00178 } 00179 00180 return returnFeatures; 00181 } 00182 00183 SpectralCentroid::FeatureSet 00184 SpectralCentroid::getRemainingFeatures() 00185 { 00186 return FeatureSet(); 00187 } 00188