comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 174:a6346812db44

* PluginSummarisingAdapter now compiles -- though doesn't actually work yet
author cannam
date Tue, 05 Aug 2008 13:38:30 +0000
parents a6981e5dafe5
children 4811fb599a97
comparison
equal deleted inserted replaced
173:a6981e5dafe5 174:a6346812db44
34 authorization. 34 authorization.
35 */ 35 */
36 36
37 #include "PluginSummarisingAdapter.h" 37 #include "PluginSummarisingAdapter.h"
38 38
39 #include <map>
40
39 namespace Vamp { 41 namespace Vamp {
40 42
41 namespace HostExt { 43 namespace HostExt {
42 44
43 class PluginSummarisingAdapter::Impl 45 class PluginSummarisingAdapter::Impl
52 void setSummarySegmentBoundaries(const SegmentBoundaries &); 54 void setSummarySegmentBoundaries(const SegmentBoundaries &);
53 55
54 FeatureSet getSummary(SummaryType type); 56 FeatureSet getSummary(SummaryType type);
55 57
56 protected: 58 protected:
59 Plugin *m_plugin;
60
57 SegmentBoundaries m_boundaries; 61 SegmentBoundaries m_boundaries;
62
63 typedef std::vector<float> ValueList;
64 typedef std::map<int, ValueList> BinValueMap;
65
66 struct OutputAccumulator {
67 int count;
68 BinValueMap values;
69 };
70
71 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
72 OutputAccumulatorMap m_accumulators;
73
74 struct OutputBinSummary {
75 float minimum;
76 float maximum;
77 float median;
78 float mode;
79 float sum;
80 float variance;
81 int count;
82 };
83
84 typedef std::map<int, OutputBinSummary> OutputSummary;
85 typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
86 typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
87
88 OutputSummarySegmentMap m_summaries;
89
90 RealTime m_lastTimestamp;
91
92 void accumulate(const FeatureSet &fs, RealTime);
93 void accumulate(int output, const Feature &f, RealTime);
94 void reduce();
58 }; 95 };
59 96
60 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) : 97 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
61 PluginWrapper(plugin) 98 PluginWrapper(plugin)
62 { 99 {
72 PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp) 109 PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
73 { 110 {
74 return m_impl->process(inputBuffers, timestamp); 111 return m_impl->process(inputBuffers, timestamp);
75 } 112 }
76 113
114 Plugin::FeatureSet
115 PluginSummarisingAdapter::getRemainingFeatures()
116 {
117 return m_impl->getRemainingFeatures();
118 }
119
77 120
78 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : 121 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
79 m_plugin(plugin), 122 m_plugin(plugin)
80 m_inputSampleRate(inputSampleRate)
81 { 123 {
82 } 124 }
83 125
84 PluginSummarisingAdapter::Impl::~Impl() 126 PluginSummarisingAdapter::Impl::~Impl()
85 { 127 {
86 } 128 }
87 129
130 Plugin::FeatureSet
131 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp)
132 {
133 FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
134 accumulate(fs, timestamp);
135 m_lastTimestamp = timestamp;
136 return fs;
137 }
138
139 Plugin::FeatureSet
140 PluginSummarisingAdapter::Impl::getRemainingFeatures()
141 {
142 FeatureSet fs = m_plugin->getRemainingFeatures();
143 accumulate(fs, m_lastTimestamp);
144 reduce();
145 return fs;
146 }
147
148 void
149 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
150 RealTime timestamp)
151 {
152 for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
153 for (FeatureList::const_iterator j = i->second.begin();
154 j != i->second.end(); ++j) {
155 accumulate(i->first, *j, timestamp);
156 }
157 }
158 }
159
160 void
161 PluginSummarisingAdapter::Impl::accumulate(int output,
162 const Feature &f,
163 RealTime timestamp)
164 {
165 //!!! use timestamp to determine which segment we're on
166 m_accumulators[output].count++;
167 for (int i = 0; i < int(f.values.size()); ++i) {
168 m_accumulators[output].values[i].push_back(f.values[i]);
169 }
170 }
171
172 void
173 PluginSummarisingAdapter::Impl::reduce()
174 {
175 RealTime segmentStart = RealTime::zeroTime; //!!!
176
177 for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
178 i != m_accumulators.end(); ++i) {
179
180 int output = i->first;
181 OutputAccumulator &accumulator = i->second;
182
183 for (BinValueMap::iterator j = accumulator.values.begin();
184 j != accumulator.values.end(); ++j) {
185
186 int bin = j->first;
187 ValueList &values = j->second;
188
189 OutputBinSummary summary;
190 summary.minimum = 0.f;
191 summary.maximum = 0.f;
192 summary.median = 0.f;
193 summary.mode = 0.f;
194 summary.sum = 0.f;
195 summary.variance = 0.f;
196 summary.count = accumulator.count;
197 if (summary.count == 0 || values.empty()) continue;
198
199 std::sort(values.begin(), values.end());
200 int sz = values.size();
201
202 summary.minimum = values[0];
203 summary.maximum = values[sz-1];
204
205 if (sz % 2 == 1) {
206 summary.median = values[sz/2];
207 } else {
208 summary.median = (values[sz/2] + values[sz/2 + 1]) / 2;
209 }
210
211 std::map<float, int> distribution;
212
213 for (int k = 0; k < sz; ++k) {
214 summary.sum += values[k];
215 ++distribution[values[k]];
216 }
217
218 int md = 0;
219
220 //!!! I don't like this. Really the mode should be the
221 //!!! value that spans the longest period of time, not the
222 //!!! one that appears in the largest number of distinct
223 //!!! features.
224
225 for (std::map<float, int>::iterator di = distribution.begin();
226 di != distribution.end(); ++di) {
227 if (di->second > md) {
228 md = di->second;
229 summary.mode = di->first;
230 }
231 }
232
233 distribution.clear();
234
235 float mean = summary.sum / summary.count;
236
237 for (int k = 0; k < sz; ++k) {
238 summary.variance += (values[k] - mean) * (values[k] - mean);
239 }
240 summary.variance /= summary.count;
241
242 m_summaries[output][segmentStart][bin] = summary;
243 }
244 }
245 }
246
247
248 }
249
250 }
251