comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 194:27cfae2a4155

* Make summarising adapter debug optional * Tidy up template generator output a bit * Clarify an error message
author cannam
date Tue, 30 Sep 2008 13:24:41 +0000
parents d1bdcd4a226f
children 1e4c6f25ded6
comparison
equal deleted inserted replaced
193:20393d30baee 194:27cfae2a4155
38 38
39 #include <map> 39 #include <map>
40 #include <cmath> 40 #include <cmath>
41 #include <climits> 41 #include <climits>
42 42
43 //#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1
44
43 namespace Vamp { 45 namespace Vamp {
44 46
45 namespace HostExt { 47 namespace HostExt {
46 48
47 class PluginSummarisingAdapter::Impl 49 class PluginSummarisingAdapter::Impl
216 218
217 void 219 void
218 PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b) 220 PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b)
219 { 221 {
220 m_boundaries = b; 222 m_boundaries = b;
223 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
221 std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl; 224 std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl;
222 for (SegmentBoundaries::const_iterator i = m_boundaries.begin(); 225 for (SegmentBoundaries::const_iterator i = m_boundaries.begin();
223 i != m_boundaries.end(); ++i) { 226 i != m_boundaries.end(); ++i) {
224 std::cerr << *i << " "; 227 std::cerr << *i << " ";
225 } 228 }
226 std::cerr << std::endl; 229 std::cerr << std::endl;
230 #endif
227 } 231 }
228 232
229 Plugin::FeatureList 233 Plugin::FeatureList
230 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output, 234 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
231 SummaryType type, 235 SummaryType type,
379 // need a separate phase to split the accumulator up into segments). 383 // need a separate phase to split the accumulator up into segments).
380 // If features spanning a boundary should be counted only in the first 384 // If features spanning a boundary should be counted only in the first
381 // segment, with their full duration, then we should store them in a 385 // segment, with their full duration, then we should store them in a
382 // single accumulator and distribute into segments only on reduce. 386 // single accumulator and distribute into segments only on reduce.
383 387
388 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
384 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl; 389 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl;
390 #endif
385 391
386 // At each process step, accumulate() is called once for each 392 // At each process step, accumulate() is called once for each
387 // feature on each output within that process's returned feature 393 // feature on each output within that process's returned feature
388 // list, and with the timestamp passed in being that of the start 394 // list, and with the timestamp passed in being that of the start
389 // of the process block. 395 // of the process block.
418 // will have to calculate the duration from the previous and 424 // will have to calculate the duration from the previous and
419 // current timestamps. 425 // current timestamps.
420 426
421 if (m_prevDurations[output] != INVALID_DURATION) { 427 if (m_prevDurations[output] != INVALID_DURATION) {
422 prevDuration = m_prevDurations[output]; 428 prevDuration = m_prevDurations[output];
429 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
423 std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl; 430 std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl;
431 #endif
424 } else { 432 } else {
425 prevDuration = timestamp - m_prevTimestamps[output]; 433 prevDuration = timestamp - m_prevTimestamps[output];
434 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
426 std::cerr << "Previous duration from diff: " << timestamp << " - " 435 std::cerr << "Previous duration from diff: " << timestamp << " - "
427 << m_prevTimestamps[output] << std::endl; 436 << m_prevTimestamps[output] << std::endl;
437 #endif
428 } 438 }
429 439
440 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
430 std::cerr << "output " << output << ": "; 441 std::cerr << "output " << output << ": ";
431
432 std::cerr << "Pushing previous duration as " << prevDuration << std::endl; 442 std::cerr << "Pushing previous duration as " << prevDuration << std::endl;
443 #endif
433 444
434 m_accumulators[output].results 445 m_accumulators[output].results
435 [m_accumulators[output].results.size() - 1] 446 [m_accumulators[output].results.size() - 1]
436 .duration = prevDuration; 447 .duration = prevDuration;
437 } 448 }
471 482
472 if (acount == 0) continue; 483 if (acount == 0) continue;
473 484
474 RealTime prevTimestamp = i->second; 485 RealTime prevTimestamp = i->second;
475 486
487 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
476 std::cerr << "output " << output << ": "; 488 std::cerr << "output " << output << ": ";
489 #endif
477 490
478 if (m_prevDurations.find(output) != m_prevDurations.end() && 491 if (m_prevDurations.find(output) != m_prevDurations.end() &&
479 m_prevDurations[output] != INVALID_DURATION) { 492 m_prevDurations[output] != INVALID_DURATION) {
480 493
494 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
481 std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl; 495 std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl;
496 #endif
482 497
483 m_accumulators[output].results[acount - 1].duration = 498 m_accumulators[output].results[acount - 1].duration =
484 m_prevDurations[output]; 499 m_prevDurations[output];
485 500
486 } else { 501 } else {
487 502
503 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
488 std::cerr << "Pushing final duration from diff as " << m_lastTimestamp << " - " << m_prevTimestamps[output] << std::endl; 504 std::cerr << "Pushing final duration from diff as " << m_lastTimestamp << " - " << m_prevTimestamps[output] << std::endl;
505 #endif
489 506
490 m_accumulators[output].results[acount - 1].duration = 507 m_accumulators[output].results[acount - 1].duration =
491 m_lastTimestamp - m_prevTimestamps[output]; 508 m_lastTimestamp - m_prevTimestamps[output];
492 } 509 }
493 510
511 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
494 std::cerr << "so duration for result no " << acount-1 << " is " 512 std::cerr << "so duration for result no " << acount-1 << " is "
495 << m_accumulators[output].results[acount-1].duration 513 << m_accumulators[output].results[acount-1].duration
496 << std::endl; 514 << std::endl;
515 #endif
497 } 516 }
498 } 517 }
499 518
500 void 519 void
501 PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t, 520 PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t,
502 RealTime &start, 521 RealTime &start,
503 RealTime &end) 522 RealTime &end)
504 { 523 {
524 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
505 std::cerr << "findSegmentBounds: t = " << t << std::endl; 525 std::cerr << "findSegmentBounds: t = " << t << std::endl;
526 #endif
506 527
507 SegmentBoundaries::const_iterator i = std::upper_bound 528 SegmentBoundaries::const_iterator i = std::upper_bound
508 (m_boundaries.begin(), m_boundaries.end(), t); 529 (m_boundaries.begin(), m_boundaries.end(), t);
509 530
510 start = RealTime::zeroTime; 531 start = RealTime::zeroTime;
515 } 536 }
516 537
517 if (i != m_boundaries.begin()) { 538 if (i != m_boundaries.begin()) {
518 start = *--i; 539 start = *--i;
519 } 540 }
520 541
542 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
521 std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl; 543 std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl;
544 #endif
522 } 545 }
523 546
524 void 547 void
525 PluginSummarisingAdapter::Impl::segment() 548 PluginSummarisingAdapter::Impl::segment()
526 { 549 {
531 i != m_accumulators.end(); ++i) { 554 i != m_accumulators.end(); ++i) {
532 555
533 int output = i->first; 556 int output = i->first;
534 OutputAccumulator &source = i->second; 557 OutputAccumulator &source = i->second;
535 558
559 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
536 std::cerr << "segment: total results for output " << output << " = " 560 std::cerr << "segment: total results for output " << output << " = "
537 << source.results.size() << std::endl; 561 << source.results.size() << std::endl;
562 #endif
538 563
539 //!!! This is basically nonsense if the results have no values 564 //!!! This is basically nonsense if the results have no values
540 //!!! (i.e. their times and counts are the only things of 565 //!!! (i.e. their times and counts are the only things of
541 //!!! interest) but perhaps it's the user's problem if they 566 //!!! interest) but perhaps it's the user's problem if they
542 //!!! ask for segmentation in that case 567 //!!! ask for segmentation in that case
548 // We need to dispose it into segments appropriately 573 // We need to dispose it into segments appropriately
549 574
550 RealTime resultStart = source.results[n].time; 575 RealTime resultStart = source.results[n].time;
551 RealTime resultEnd = resultStart + source.results[n].duration; 576 RealTime resultEnd = resultStart + source.results[n].duration;
552 577
578 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
553 std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl; 579 std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl;
580 #endif
554 581
555 RealTime segmentStart = RealTime::zeroTime; 582 RealTime segmentStart = RealTime::zeroTime;
556 RealTime segmentEnd = resultEnd - RealTime(1, 0); 583 RealTime segmentEnd = resultEnd - RealTime(1, 0);
557 584
558 while (segmentEnd < resultEnd) { 585 while (segmentEnd < resultEnd) {
570 Result chunk; 597 Result chunk;
571 chunk.time = chunkStart; 598 chunk.time = chunkStart;
572 chunk.duration = chunkEnd - chunkStart; 599 chunk.duration = chunkEnd - chunkStart;
573 chunk.values = source.results[n].values; 600 chunk.values = source.results[n].values;
574 601
602 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
575 std::cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << std::endl; 603 std::cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << std::endl;
604 #endif
576 605
577 m_segmentedAccumulators[output][segmentStart].results 606 m_segmentedAccumulators[output][segmentStart].results
578 .push_back(chunk); 607 .push_back(chunk);
579 608
580 resultStart = chunkEnd; 609 resultStart = chunkEnd;
635 RealTime segmentStart = j->first; 664 RealTime segmentStart = j->first;
636 OutputAccumulator &accumulator = j->second; 665 OutputAccumulator &accumulator = j->second;
637 666
638 int sz = accumulator.results.size(); 667 int sz = accumulator.results.size();
639 668
669 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
640 std::cerr << "reduce: segment starting at " << segmentStart 670 std::cerr << "reduce: segment starting at " << segmentStart
641 << " on output " << output << " has " << sz << " result(s)" << std::endl; 671 << " on output " << output << " has " << sz << " result(s)" << std::endl;
672 #endif
642 673
643 double totalDuration = 0.0; 674 double totalDuration = 0.0;
644 //!!! is this right? 675 //!!! is this right?
645 if (sz > 0) { 676 if (sz > 0) {
677 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
646 std::cerr << "last time = " << accumulator.results[sz-1].time 678 std::cerr << "last time = " << accumulator.results[sz-1].time
647 << ", duration = " << accumulator.results[sz-1].duration 679 << ", duration = " << accumulator.results[sz-1].duration
648 << std::endl; 680 << std::endl;
681 #endif
649 totalDuration = toSec((accumulator.results[sz-1].time + 682 totalDuration = toSec((accumulator.results[sz-1].time +
650 accumulator.results[sz-1].duration) - 683 accumulator.results[sz-1].duration) -
651 segmentStart); 684 segmentStart);
652 } 685 }
653 686
693 std::sort(valvec.begin(), valvec.end()); 726 std::sort(valvec.begin(), valvec.end());
694 727
695 summary.minimum = valvec[0].value; 728 summary.minimum = valvec[0].value;
696 summary.maximum = valvec[sz-1].value; 729 summary.maximum = valvec[sz-1].value;
697 730
731 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
698 std::cerr << "total duration = " << totalDuration << std::endl; 732 std::cerr << "total duration = " << totalDuration << std::endl;
699 733 #endif
734
735 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
700 std::cerr << "value vector for medians:" << std::endl; 736 std::cerr << "value vector for medians:" << std::endl;
701 for (int k = 0; k < sz; ++k) { 737 for (int k = 0; k < sz; ++k) {
702 std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") "; 738 std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") ";
703 } 739 }
704 std::cerr << std::endl; 740 std::cerr << std::endl;
741 #endif
705 742
706 if (sz % 2 == 1) { 743 if (sz % 2 == 1) {
707 summary.median = valvec[sz/2].value; 744 summary.median = valvec[sz/2].value;
708 } else { 745 } else {
709 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2; 746 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2;
718 summary.median_c = valvec[k].value; 755 summary.median_c = valvec[k].value;
719 break; 756 break;
720 } 757 }
721 } 758 }
722 759
760 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
723 std::cerr << "median_c = " << summary.median_c << std::endl; 761 std::cerr << "median_c = " << summary.median_c << std::endl;
724 std::cerr << "median = " << summary.median << std::endl; 762 std::cerr << "median = " << summary.median << std::endl;
763 #endif
725 764
726 std::map<float, int> distribution; 765 std::map<float, int> distribution;
727 766
728 for (int k = 0; k < sz; ++k) { 767 for (int k = 0; k < sz; ++k) {
729 summary.sum += accumulator.results[k].values[bin]; 768 summary.sum += accumulator.results[k].values[bin];
769 double value = accumulator.results[k].values[bin] 808 double value = accumulator.results[k].values[bin]
770 * toSec(accumulator.results[k].duration); 809 * toSec(accumulator.results[k].duration);
771 sum_c += value; 810 sum_c += value;
772 } 811 }
773 812
813 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
774 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = " 814 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
775 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl; 815 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl;
816 #endif
776 817
777 summary.mean_c = sum_c / totalDuration; 818 summary.mean_c = sum_c / totalDuration;
778 819
779 for (int k = 0; k < sz; ++k) { 820 for (int k = 0; k < sz; ++k) {
780 double value = accumulator.results[k].values[bin] 821 double value = accumulator.results[k].values[bin]
786 summary.variance_c /= summary.count; 827 summary.variance_c /= summary.count;
787 } 828 }
788 829
789 float mean = summary.sum / summary.count; 830 float mean = summary.sum / summary.count;
790 831
832 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
791 std::cerr << "mean = " << summary.sum << " / " << summary.count << " = " 833 std::cerr << "mean = " << summary.sum << " / " << summary.count << " = "
792 << summary.sum / summary.count << std::endl; 834 << summary.sum / summary.count << std::endl;
835 #endif
793 836
794 for (int k = 0; k < sz; ++k) { 837 for (int k = 0; k < sz; ++k) {
795 float value = accumulator.results[k].values[bin]; 838 float value = accumulator.results[k].values[bin];
796 summary.variance += (value - mean) * (value - mean); 839 summary.variance += (value - mean) * (value - mean);
797 } 840 }