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