comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 184:26c200c3fc42

* Fixes to summarisation (calculation of durations)
author cannam
date Wed, 10 Sep 2008 14:54:25 +0000
parents c053ababbf7e
children 701505ac170c
comparison
equal deleted inserted replaced
183:c053ababbf7e 184:26c200c3fc42
36 36
37 #include "PluginSummarisingAdapter.h" 37 #include "PluginSummarisingAdapter.h"
38 38
39 #include <map> 39 #include <map>
40 #include <cmath> 40 #include <cmath>
41 #include <climits>
41 42
42 namespace Vamp { 43 namespace Vamp {
43 44
44 namespace HostExt { 45 namespace HostExt {
45 46
115 bool m_reduced; 116 bool m_reduced;
116 RealTime m_lastTimestamp; 117 RealTime m_lastTimestamp;
117 118
118 void accumulate(const FeatureSet &fs, RealTime, bool final); 119 void accumulate(const FeatureSet &fs, RealTime, bool final);
119 void accumulate(int output, const Feature &f, RealTime, bool final); 120 void accumulate(int output, const Feature &f, RealTime, bool final);
121 void accumulateFinalDurations();
120 void reduce(); 122 void reduce();
121 }; 123 };
124
125 static RealTime INVALID_DURATION(INT_MIN, INT_MIN);
122 126
123 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) : 127 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
124 PluginWrapper(plugin) 128 PluginWrapper(plugin)
125 { 129 {
126 m_impl = new Impl(plugin, m_inputSampleRate); 130 m_impl = new Impl(plugin, m_inputSampleRate);
318 { 322 {
319 //!!! to do: use timestamp to determine which segment we're on 323 //!!! to do: use timestamp to determine which segment we're on
320 324
321 m_accumulators[output].count++; 325 m_accumulators[output].count++;
322 326
323 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << std::endl; 327 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl;
324 328
325 //!!! also, this will not work if we are called repeatedly with 329 // At each process step, accumulate() is called once for each
326 //!!! the same timestamp -- no values will be registered until a 330 // feature on each output within that process's returned feature
327 //!!! new timestamp is seen -- we need a better test for "not 331 // list, and with the timestamp passed in being that of the start
328 //!!! first result" below 332 // of the process block.
329 333
330 if (m_prevDurations[output] == RealTime::zeroTime) { 334 // At the end (in getRemainingFeatures), accumulate() is called
331 if (m_prevTimestamps.find(output) != m_prevTimestamps.end()) { 335 // once for each feature on each output within the feature list
332 m_prevDurations[output] = timestamp - m_prevTimestamps[output]; 336 // returned by getRemainingFeatures, and with the timestamp being
337 // the same as the last process block and final set to true.
338
339 // (What if getRemainingFeatures doesn't return any features? We
340 // still need to ensure that the final duration is written. Need
341 // a separate function to close the durations.)
342
343 // At each call, we pull out the value for the feature and stuff
344 // it into the accumulator's appropriate values array; and we
345 // calculate the duration for the _previous_ feature, or pull it
346 // from the prevDurations array if the previous feature had a
347 // duration in its structure, and stuff that into the
348 // accumulator's appropriate durations array.
349
350 if (m_prevDurations.find(output) != m_prevDurations.end()) {
351
352 // Not the first time accumulate has been called for this
353 // output -- there has been a previous feature
354
355 RealTime prevDuration;
356
357 // Note that m_prevDurations[output] only contains the
358 // duration field that was contained in the previous feature.
359 // If it didn't have an explicit duration,
360 // m_prevDurations[output] should be INVALID_DURATION and we
361 // will have to calculate the duration from the previous and
362 // current timestamps.
363
364 if (m_prevDurations[output] != INVALID_DURATION) {
365 prevDuration = m_prevDurations[output];
366 std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl;
367 } else {
368 prevDuration = timestamp - m_prevTimestamps[output];
369 std::cerr << "Previous duration from diff: " << timestamp << " - "
370 << m_prevTimestamps[output] << std::endl;
333 } 371 }
334 } 372
335 if (m_prevDurations[output] != RealTime::zeroTime || 373 std::cerr << "output " << output << ": ";
336 !m_accumulators[output].durations.empty()) { 374
337 // ... i.e. if not first result. We don't push a duration 375 std::cerr << "Pushing previous duration as " << prevDuration << std::endl;
338 // when we process the first result; then the duration we push 376 m_accumulators[output].durations.push_back(prevDuration);
339 // each time is that for the result before the one we're 377 }
340 // processing, and we push an extra one at the end. This 378
341 // permits handling the case where the feature itself doesn't 379 if (f.hasDuration) m_prevDurations[output] = f.duration;
342 // have a duration field, and we have to calculate it from the 380 else m_prevDurations[output] = INVALID_DURATION;
343 // time to the following feature. The net effect is simply
344 // that values[n] and durations[n] refer to the same result.
345 m_accumulators[output].durations.push_back(m_prevDurations[output]);
346 }
347 381
348 m_prevTimestamps[output] = timestamp; 382 m_prevTimestamps[output] = timestamp;
383 if (timestamp > m_lastTimestamp) m_lastTimestamp = timestamp;
349 384
350 for (int i = 0; i < int(f.values.size()); ++i) { 385 for (int i = 0; i < int(f.values.size()); ++i) {
351 m_accumulators[output].values[i].push_back(f.values[i]); 386 m_accumulators[output].values[i].push_back(f.values[i]);
352 } 387 }
353 388 }
354 if (final) { 389
355 RealTime finalDuration; 390 void
356 if (f.hasDuration) finalDuration = f.duration; 391 PluginSummarisingAdapter::Impl::accumulateFinalDurations()
357 m_accumulators[output].durations.push_back(finalDuration); 392 {
358 } 393 for (OutputTimestampMap::iterator i = m_prevTimestamps.begin();
359 394 i != m_prevTimestamps.end(); ++i) {
360 if (f.hasDuration) m_prevDurations[output] = f.duration; 395
361 else m_prevDurations[output] = RealTime::zeroTime; 396 int output = i->first;
397 RealTime prevTimestamp = i->second;
398
399 std::cerr << "output " << output << ": ";
400
401 if (m_prevDurations.find(output) != m_prevDurations.end() &&
402 m_prevDurations[output] != INVALID_DURATION) {
403
404 std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl;
405
406 m_accumulators[output].durations.push_back(m_prevDurations[output]);
407
408 } else {
409
410 std::cerr << "Pushing final duration from diff as " << m_lastTimestamp << " - " << m_prevTimestamps[output] << std::endl;
411
412 m_accumulators[output].durations.push_back
413 (m_lastTimestamp - m_prevTimestamps[output]);
414 }
415 }
362 } 416 }
363 417
364 struct ValueDurationFloatPair 418 struct ValueDurationFloatPair
365 { 419 {
366 float value; 420 float value;
384 } 438 }
385 439
386 void 440 void
387 PluginSummarisingAdapter::Impl::reduce() 441 PluginSummarisingAdapter::Impl::reduce()
388 { 442 {
443 accumulateFinalDurations();
444
389 RealTime segmentStart = RealTime::zeroTime; //!!! 445 RealTime segmentStart = RealTime::zeroTime; //!!!
390 446
391 for (OutputAccumulatorMap::iterator i = m_accumulators.begin(); 447 for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
392 i != m_accumulators.end(); ++i) { 448 i != m_accumulators.end(); ++i) {
393 449
515 double value = values[k] * toSec(durations[k]); 571 double value = values[k] * toSec(durations[k]);
516 sum_c += value; 572 sum_c += value;
517 } 573 }
518 574
519 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = " 575 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
520 << sum_c / totalDuration << std::endl; 576 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl;
521 577
522 summary.mean_c = sum_c / totalDuration; 578 summary.mean_c = sum_c / totalDuration;
523 579
524 for (int k = 0; k < sz; ++k) { 580 for (int k = 0; k < sz; ++k) {
525 double value = values[k] * toSec(durations[k]); 581 double value = values[k] * toSec(durations[k]);