comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 183:c053ababbf7e

* Fixes to continuous time averaging
author cannam
date Fri, 05 Sep 2008 13:52:57 +0000
parents 3fcac0f3afdc
children 26c200c3fc42
comparison
equal deleted inserted replaced
182:3fcac0f3afdc 183:c053ababbf7e
81 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap; 81 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
82 OutputAccumulatorMap m_accumulators; // output number -> accumulator 82 OutputAccumulatorMap m_accumulators; // output number -> accumulator
83 83
84 typedef std::map<int, RealTime> OutputTimestampMap; 84 typedef std::map<int, RealTime> OutputTimestampMap;
85 OutputTimestampMap m_prevTimestamps; // output number -> timestamp 85 OutputTimestampMap m_prevTimestamps; // output number -> timestamp
86 OutputTimestampMap m_prevDurations; // output number -> durations
86 87
87 struct OutputBinSummary { 88 struct OutputBinSummary {
88 89
89 int count; 90 int count;
90 91
109 typedef std::map<RealTime, OutputSummary> SummarySegmentMap; 110 typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
110 typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap; 111 typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
111 112
112 OutputSummarySegmentMap m_summaries; 113 OutputSummarySegmentMap m_summaries;
113 114
115 bool m_reduced;
114 RealTime m_lastTimestamp; 116 RealTime m_lastTimestamp;
115 RealTime m_prevDuration;
116 117
117 void accumulate(const FeatureSet &fs, RealTime, bool final); 118 void accumulate(const FeatureSet &fs, RealTime, bool final);
118 void accumulate(int output, const Feature &f, RealTime, bool final); 119 void accumulate(int output, const Feature &f, RealTime, bool final);
119 void reduce(); 120 void reduce();
120 }; 121 };
157 return m_impl->getSummaryForAllOutputs(type, avg); 158 return m_impl->getSummaryForAllOutputs(type, avg);
158 } 159 }
159 160
160 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : 161 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
161 m_plugin(plugin), 162 m_plugin(plugin),
162 m_inputSampleRate(inputSampleRate) 163 m_inputSampleRate(inputSampleRate),
164 m_reduced(false)
163 { 165 {
164 } 166 }
165 167
166 PluginSummarisingAdapter::Impl::~Impl() 168 PluginSummarisingAdapter::Impl::~Impl()
167 { 169 {
168 } 170 }
169 171
170 Plugin::FeatureSet 172 Plugin::FeatureSet
171 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp) 173 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp)
172 { 174 {
175 if (m_reduced) {
176 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
177 }
173 FeatureSet fs = m_plugin->process(inputBuffers, timestamp); 178 FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
174 accumulate(fs, timestamp, false); 179 accumulate(fs, timestamp, false);
175 m_lastTimestamp = timestamp; 180 m_lastTimestamp = timestamp;
176 return fs; 181 return fs;
177 } 182 }
178 183
179 Plugin::FeatureSet 184 Plugin::FeatureSet
180 PluginSummarisingAdapter::Impl::getRemainingFeatures() 185 PluginSummarisingAdapter::Impl::getRemainingFeatures()
181 { 186 {
187 if (m_reduced) {
188 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
189 }
182 FeatureSet fs = m_plugin->getRemainingFeatures(); 190 FeatureSet fs = m_plugin->getRemainingFeatures();
183 accumulate(fs, m_lastTimestamp, true); 191 accumulate(fs, m_lastTimestamp, true);
184 reduce();
185 return fs; 192 return fs;
186 } 193 }
187 194
188 Plugin::FeatureList 195 Plugin::FeatureList
189 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output, 196 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
190 SummaryType type, 197 SummaryType type,
191 AveragingMethod avg) 198 AveragingMethod avg)
192 { 199 {
200 if (!m_reduced) reduce();
201
193 bool continuous = (avg == ContinuousTimeAverage); 202 bool continuous = (avg == ContinuousTimeAverage);
194 203
195 //!!! need to ensure that this is only called after processing is
196 //!!! complete (at the moment processing is "completed" in the
197 //!!! call to getRemainingFeatures, but we don't want to require
198 //!!! the host to call getRemainingFeatures at all unless it
199 //!!! actually wants the raw features too -- calling getSummary
200 //!!! should be enough -- we do need to ensure that all data has
201 //!!! been processed though!)
202 FeatureList fl; 204 FeatureList fl;
203 for (SummarySegmentMap::const_iterator i = m_summaries[output].begin(); 205 for (SummarySegmentMap::const_iterator i = m_summaries[output].begin();
204 i != m_summaries[output].end(); ++i) { 206 i != m_summaries[output].end(); ++i) {
205 207
206 Feature f; 208 Feature f;
278 280
279 Plugin::FeatureSet 281 Plugin::FeatureSet
280 PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type, 282 PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
281 AveragingMethod avg) 283 AveragingMethod avg)
282 { 284 {
285 if (!m_reduced) reduce();
286
283 FeatureSet fs; 287 FeatureSet fs;
284 for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin(); 288 for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin();
285 i != m_summaries.end(); ++i) { 289 i != m_summaries.end(); ++i) {
286 fs[i->first] = getSummaryForOutput(i->first, type, avg); 290 fs[i->first] = getSummaryForOutput(i->first, type, avg);
287 } 291 }
316 320
317 m_accumulators[output].count++; 321 m_accumulators[output].count++;
318 322
319 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << std::endl; 323 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << std::endl;
320 324
321 //!!! m_prevDuration needs to be per output
322
323 //!!! also, this will not work if we are called repeatedly with 325 //!!! also, this will not work if we are called repeatedly with
324 //!!! the same timestamp -- no values will be registered until a 326 //!!! the same timestamp -- no values will be registered until a
325 //!!! new timestamp is seen -- we need a better test for "not 327 //!!! new timestamp is seen -- we need a better test for "not
326 //!!! first result" below 328 //!!! first result" below
327 329
328 if (m_prevDuration == RealTime::zeroTime) { 330 if (m_prevDurations[output] == RealTime::zeroTime) {
329 if (m_prevTimestamps.find(output) != m_prevTimestamps.end()) { 331 if (m_prevTimestamps.find(output) != m_prevTimestamps.end()) {
330 m_prevDuration = timestamp - m_prevTimestamps[output]; 332 m_prevDurations[output] = timestamp - m_prevTimestamps[output];
331 } 333 }
332 } 334 }
333 if (m_prevDuration != RealTime::zeroTime || 335 if (m_prevDurations[output] != RealTime::zeroTime ||
334 !m_accumulators[output].durations.empty()) { 336 !m_accumulators[output].durations.empty()) {
335 // ... i.e. if not first result. We don't push a duration 337 // ... i.e. if not first result. We don't push a duration
336 // when we process the first result; then the duration we push 338 // when we process the first result; then the duration we push
337 // each time is that for the result before the one we're 339 // each time is that for the result before the one we're
338 // processing, and we push an extra one at the end. This 340 // processing, and we push an extra one at the end. This
339 // permits handling the case where the feature itself doesn't 341 // permits handling the case where the feature itself doesn't
340 // have a duration field, and we have to calculate it from the 342 // have a duration field, and we have to calculate it from the
341 // time to the following feature. The net effect is simply 343 // time to the following feature. The net effect is simply
342 // that values[n] and durations[n] refer to the same result. 344 // that values[n] and durations[n] refer to the same result.
343 m_accumulators[output].durations.push_back(m_prevDuration); 345 m_accumulators[output].durations.push_back(m_prevDurations[output]);
344 } 346 }
345 347
346 m_prevTimestamps[output] = timestamp; 348 m_prevTimestamps[output] = timestamp;
347 349
348 for (int i = 0; i < int(f.values.size()); ++i) { 350 for (int i = 0; i < int(f.values.size()); ++i) {
353 RealTime finalDuration; 355 RealTime finalDuration;
354 if (f.hasDuration) finalDuration = f.duration; 356 if (f.hasDuration) finalDuration = f.duration;
355 m_accumulators[output].durations.push_back(finalDuration); 357 m_accumulators[output].durations.push_back(finalDuration);
356 } 358 }
357 359
358 if (f.hasDuration) m_prevDuration = f.duration; 360 if (f.hasDuration) m_prevDurations[output] = f.duration;
359 else m_prevDuration = RealTime::zeroTime; 361 else m_prevDurations[output] = RealTime::zeroTime;
360 } 362 }
361 363
362 struct ValueDurationFloatPair 364 struct ValueDurationFloatPair
363 { 365 {
364 float value; 366 float value;
543 m_summaries[output][segmentStart][bin] = summary; 545 m_summaries[output][segmentStart][bin] = summary;
544 } 546 }
545 } 547 }
546 548
547 m_accumulators.clear(); 549 m_accumulators.clear();
548 } 550 m_reduced = true;
549 551 }
550 552
551 } 553
552 554 }
553 } 555
554 556 }
557