82d80b81000532bc518c31f2b4bfb76a34e096b9
[ardour.git] / libs / vamp-plugins / SpectralCentroid.cpp
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 #include "SpectralCentroid.h"
38
39 using std::string;
40 using std::vector;
41 using std::cerr;
42 using std::endl;
43
44 #include <cmath>
45
46
47 SpectralCentroid::SpectralCentroid(float inputSampleRate) :
48     Plugin(inputSampleRate),
49     m_stepSize(0),
50     m_blockSize(0)
51 {
52 }
53
54 SpectralCentroid::~SpectralCentroid()
55 {
56 }
57
58 string
59 SpectralCentroid::getIdentifier() const
60 {
61     return "spectralcentroid";
62 }
63
64 string
65 SpectralCentroid::getName() const
66 {
67     return "Spectral Centroid";
68 }
69
70 string
71 SpectralCentroid::getDescription() const
72 {
73     return "Calculate the centroid frequency of the spectrum of the input signal";
74 }
75
76 string
77 SpectralCentroid::getMaker() const
78 {
79     return "Vamp SDK Example Plugins";
80 }
81
82 int
83 SpectralCentroid::getPluginVersion() const
84 {
85     return 2;
86 }
87
88 string
89 SpectralCentroid::getCopyright() const
90 {
91     return "Freely redistributable (BSD license)";
92 }
93
94 bool
95 SpectralCentroid::initialise(size_t channels, size_t stepSize, size_t blockSize)
96 {
97     if (channels < getMinChannelCount() ||
98         channels > getMaxChannelCount()) return false;
99
100     m_stepSize = stepSize;
101     m_blockSize = blockSize;
102
103     return true;
104 }
105
106 void
107 SpectralCentroid::reset()
108 {
109 }
110
111 SpectralCentroid::OutputList
112 SpectralCentroid::getOutputDescriptors() const
113 {
114     OutputList list;
115
116     OutputDescriptor d;
117     d.identifier = "logcentroid";
118     d.name = "Log Frequency Centroid";
119     d.description = "Centroid of the log weighted frequency spectrum";
120     d.unit = "Hz";
121     d.hasFixedBinCount = true;
122     d.binCount = 1;
123     d.hasKnownExtents = false;
124     d.isQuantized = false;
125     d.sampleType = OutputDescriptor::OneSamplePerStep;
126     list.push_back(d);
127
128     d.identifier = "linearcentroid";
129     d.name = "Linear Frequency Centroid";
130     d.description = "Centroid of the linear frequency spectrum";
131     list.push_back(d);
132
133     return list;
134 }
135
136 SpectralCentroid::FeatureSet
137 SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime)
138 {
139     if (m_stepSize == 0) {
140         cerr << "ERROR: SpectralCentroid::process: "
141              << "SpectralCentroid has not been initialised"
142              << endl;
143         return FeatureSet();
144     }
145
146     double numLin = 0.0, numLog = 0.0, denom = 0.0;
147
148     for (size_t i = 1; i <= m_blockSize/2; ++i) {
149         double freq = (double(i) * m_inputSampleRate) / m_blockSize;
150         double real = inputBuffers[0][i*2];
151         double imag = inputBuffers[0][i*2 + 1];
152         double power = sqrt(real * real + imag * imag) / (m_blockSize/2);
153         numLin += freq * power;
154         numLog += log10f(freq) * power;
155         denom += power;
156     }
157
158     FeatureSet returnFeatures;
159
160 //    std::cerr << "power " << denom << ", block size " << m_blockSize << std::endl;
161
162     if (denom != 0.0) {
163         float centroidLin = float(numLin / denom);
164         float centroidLog = powf(10, float(numLog / denom));
165
166         Feature feature;
167         feature.hasTimestamp = false;
168         if (!std::isnan(centroidLog) && !std::isinf(centroidLog)) {
169             feature.values.push_back(centroidLog);
170         }
171         returnFeatures[0].push_back(feature);
172
173         feature.values.clear();
174         if (!std::isnan(centroidLin) && !std::isinf(centroidLin)) {
175             feature.values.push_back(centroidLin);
176         }
177         returnFeatures[1].push_back(feature);
178     }
179
180     return returnFeatures;
181 }
182
183 SpectralCentroid::FeatureSet
184 SpectralCentroid::getRemainingFeatures()
185 {
186     return FeatureSet();
187 }
188