Mercurial > hg > vamp-plugin-sdk
comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 175:4811fb599a97
* summarising adapter might sort of work now -- quite untested though
author | cannam |
---|---|
date | Tue, 05 Aug 2008 15:15:37 +0000 |
parents | a6346812db44 |
children | adfb6348881c |
comparison
equal
deleted
inserted
replaced
174:a6346812db44 | 175:4811fb599a97 |
---|---|
35 */ | 35 */ |
36 | 36 |
37 #include "PluginSummarisingAdapter.h" | 37 #include "PluginSummarisingAdapter.h" |
38 | 38 |
39 #include <map> | 39 #include <map> |
40 #include <cmath> | |
40 | 41 |
41 namespace Vamp { | 42 namespace Vamp { |
42 | 43 |
43 namespace HostExt { | 44 namespace HostExt { |
44 | 45 |
51 FeatureSet process(const float *const *inputBuffers, RealTime timestamp); | 52 FeatureSet process(const float *const *inputBuffers, RealTime timestamp); |
52 FeatureSet getRemainingFeatures(); | 53 FeatureSet getRemainingFeatures(); |
53 | 54 |
54 void setSummarySegmentBoundaries(const SegmentBoundaries &); | 55 void setSummarySegmentBoundaries(const SegmentBoundaries &); |
55 | 56 |
56 FeatureSet getSummary(SummaryType type); | 57 FeatureList getSummary(int output, SummaryType type); |
57 | 58 |
58 protected: | 59 protected: |
59 Plugin *m_plugin; | 60 Plugin *m_plugin; |
60 | 61 |
61 SegmentBoundaries m_boundaries; | 62 SegmentBoundaries m_boundaries; |
115 PluginSummarisingAdapter::getRemainingFeatures() | 116 PluginSummarisingAdapter::getRemainingFeatures() |
116 { | 117 { |
117 return m_impl->getRemainingFeatures(); | 118 return m_impl->getRemainingFeatures(); |
118 } | 119 } |
119 | 120 |
121 Plugin::FeatureList | |
122 PluginSummarisingAdapter::getSummary(int output, SummaryType type) | |
123 { | |
124 return m_impl->getSummary(output, type); | |
125 } | |
120 | 126 |
121 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : | 127 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : |
122 m_plugin(plugin) | 128 m_plugin(plugin) |
123 { | 129 { |
124 } | 130 } |
141 { | 147 { |
142 FeatureSet fs = m_plugin->getRemainingFeatures(); | 148 FeatureSet fs = m_plugin->getRemainingFeatures(); |
143 accumulate(fs, m_lastTimestamp); | 149 accumulate(fs, m_lastTimestamp); |
144 reduce(); | 150 reduce(); |
145 return fs; | 151 return fs; |
152 } | |
153 | |
154 Plugin::FeatureList | |
155 PluginSummarisingAdapter::Impl::getSummary(int output, SummaryType type) | |
156 { | |
157 //!!! need to ensure that this is only called after processing is | |
158 //!!! complete (at the moment processing is "completed" in the | |
159 //!!! call to getRemainingFeatures, but we don't want to require | |
160 //!!! the host to call getRemainingFeatures at all unless it | |
161 //!!! actually wants the raw features too -- calling getSummary | |
162 //!!! should be enough -- we do need to ensure that all data has | |
163 //!!! been processed though!) | |
164 FeatureList fl; | |
165 for (SummarySegmentMap::const_iterator i = m_summaries[output].begin(); | |
166 i != m_summaries[output].end(); ++i) { | |
167 Feature f; | |
168 f.hasTimestamp = true; | |
169 f.timestamp = i->first; | |
170 f.hasDuration = false; | |
171 for (OutputSummary::const_iterator j = i->second.begin(); | |
172 j != i->second.end(); ++j) { | |
173 | |
174 // these will be ordered by bin number, and no bin numbers | |
175 // will be missing except at the end (because of the way | |
176 // the accumulators were initially filled in accumulate()) | |
177 | |
178 const OutputBinSummary &summary = j->second; | |
179 float result = 0.f; | |
180 | |
181 switch (type) { | |
182 | |
183 case Minimum: | |
184 result = summary.minimum; | |
185 break; | |
186 | |
187 case Maximum: | |
188 result = summary.maximum; | |
189 break; | |
190 | |
191 case Mean: | |
192 if (summary.count) { | |
193 result = summary.sum / summary.count; | |
194 } | |
195 break; | |
196 | |
197 case Median: | |
198 result = summary.median; | |
199 break; | |
200 | |
201 case Mode: | |
202 result = summary.mode; | |
203 break; | |
204 | |
205 case Sum: | |
206 result = summary.sum; | |
207 break; | |
208 | |
209 case Variance: | |
210 result = summary.variance; | |
211 break; | |
212 | |
213 case StandardDeviation: | |
214 result = sqrtf(summary.variance); | |
215 break; | |
216 | |
217 case Count: | |
218 result = summary.count; | |
219 break; | |
220 } | |
221 } | |
222 | |
223 fl.push_back(f); | |
224 } | |
225 return fl; | |
146 } | 226 } |
147 | 227 |
148 void | 228 void |
149 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs, | 229 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs, |
150 RealTime timestamp) | 230 RealTime timestamp) |
218 int md = 0; | 298 int md = 0; |
219 | 299 |
220 //!!! I don't like this. Really the mode should be the | 300 //!!! I don't like this. Really the mode should be the |
221 //!!! value that spans the longest period of time, not the | 301 //!!! value that spans the longest period of time, not the |
222 //!!! one that appears in the largest number of distinct | 302 //!!! one that appears in the largest number of distinct |
223 //!!! features. | 303 //!!! features. I suppose that a median by time rather |
304 //!!! than number of features would also be useful. | |
224 | 305 |
225 for (std::map<float, int>::iterator di = distribution.begin(); | 306 for (std::map<float, int>::iterator di = distribution.begin(); |
226 di != distribution.end(); ++di) { | 307 di != distribution.end(); ++di) { |
227 if (di->second > md) { | 308 if (di->second > md) { |
228 md = di->second; | 309 md = di->second; |
240 summary.variance /= summary.count; | 321 summary.variance /= summary.count; |
241 | 322 |
242 m_summaries[output][segmentStart][bin] = summary; | 323 m_summaries[output][segmentStart][bin] = summary; |
243 } | 324 } |
244 } | 325 } |
245 } | 326 |
246 | 327 m_accumulators.clear(); |
247 | 328 } |
248 } | 329 |
249 | 330 |
250 } | 331 } |
251 | 332 |
333 } | |
334 |