Mercurial > hg > vamp-plugin-sdk
comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 187:ed8aa954e72f
* Segmentation work for summarisation
author | cannam |
---|---|
date | Fri, 12 Sep 2008 16:27:07 +0000 |
parents | 8311695c13f9 |
children | 5a6446a2346a |
comparison
equal
deleted
inserted
replaced
186:8311695c13f9 | 187:ed8aa954e72f |
---|---|
87 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap; | 87 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap; |
88 OutputAccumulatorMap m_accumulators; // output number -> accumulator | 88 OutputAccumulatorMap m_accumulators; // output number -> accumulator |
89 | 89 |
90 typedef std::map<RealTime, OutputAccumulator> SegmentAccumulatorMap; | 90 typedef std::map<RealTime, OutputAccumulator> SegmentAccumulatorMap; |
91 typedef std::map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap; | 91 typedef std::map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap; |
92 OutputSegmentAccumulatorMap m_segmentedAccumulators; | 92 OutputSegmentAccumulatorMap m_segmentedAccumulators; // output -> segmented |
93 | 93 |
94 typedef std::map<int, RealTime> OutputTimestampMap; | 94 typedef std::map<int, RealTime> OutputTimestampMap; |
95 OutputTimestampMap m_prevTimestamps; // output number -> timestamp | 95 OutputTimestampMap m_prevTimestamps; // output number -> timestamp |
96 OutputTimestampMap m_prevDurations; // output number -> durations | 96 OutputTimestampMap m_prevDurations; // output number -> durations |
97 | 97 |
156 PluginSummarisingAdapter::getRemainingFeatures() | 156 PluginSummarisingAdapter::getRemainingFeatures() |
157 { | 157 { |
158 return m_impl->getRemainingFeatures(); | 158 return m_impl->getRemainingFeatures(); |
159 } | 159 } |
160 | 160 |
161 void | |
162 PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries &b) | |
163 { | |
164 m_impl->setSummarySegmentBoundaries(b); | |
165 } | |
166 | |
161 Plugin::FeatureList | 167 Plugin::FeatureList |
162 PluginSummarisingAdapter::getSummaryForOutput(int output, | 168 PluginSummarisingAdapter::getSummaryForOutput(int output, |
163 SummaryType type, | 169 SummaryType type, |
164 AveragingMethod avg) | 170 AveragingMethod avg) |
165 { | 171 { |
204 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl; | 210 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl; |
205 } | 211 } |
206 FeatureSet fs = m_plugin->getRemainingFeatures(); | 212 FeatureSet fs = m_plugin->getRemainingFeatures(); |
207 accumulate(fs, m_lastTimestamp, true); | 213 accumulate(fs, m_lastTimestamp, true); |
208 return fs; | 214 return fs; |
215 } | |
216 | |
217 void | |
218 PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b) | |
219 { | |
220 m_boundaries = b; | |
221 std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl; | |
222 for (SegmentBoundaries::const_iterator i = m_boundaries.begin(); | |
223 i != m_boundaries.end(); ++i) { | |
224 std::cerr << *i << " "; | |
225 } | |
226 std::cerr << std::endl; | |
209 } | 227 } |
210 | 228 |
211 Plugin::FeatureList | 229 Plugin::FeatureList |
212 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output, | 230 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output, |
213 SummaryType type, | 231 SummaryType type, |
475 RealTime &start, | 493 RealTime &start, |
476 RealTime &end) | 494 RealTime &end) |
477 { | 495 { |
478 std::cerr << "findSegmentBounds: t = " << t << std::endl; | 496 std::cerr << "findSegmentBounds: t = " << t << std::endl; |
479 | 497 |
480 SegmentBoundaries::const_iterator i = std::lower_bound | 498 SegmentBoundaries::const_iterator i = std::upper_bound |
481 (m_boundaries.begin(), m_boundaries.end(), t); | 499 (m_boundaries.begin(), m_boundaries.end(), t); |
482 | 500 |
483 start = RealTime::zeroTime; | 501 start = RealTime::zeroTime; |
484 end = m_lastTimestamp; | 502 end = m_lastTimestamp; |
485 | 503 |
486 if (i != m_boundaries.end()) { | 504 if (i != m_boundaries.end()) { |
487 | 505 |
488 start = *i; | 506 end = *i; |
489 | 507 |
490 if (++i != m_boundaries.end()) { | 508 if (i != m_boundaries.begin()) { |
491 end = *i; | 509 start = *--i; |
492 } | 510 } |
493 } | 511 } |
494 | 512 |
495 std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl; | 513 std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl; |
496 } | 514 } |
505 i != m_accumulators.end(); ++i) { | 523 i != m_accumulators.end(); ++i) { |
506 | 524 |
507 int output = i->first; | 525 int output = i->first; |
508 OutputAccumulator &source = i->second; | 526 OutputAccumulator &source = i->second; |
509 | 527 |
528 //!!! This is basically nonsense if the results have no values | |
529 //!!! (i.e. their times and counts are the only things of | |
530 //!!! interest) but perhaps it's the user's problem if they | |
531 //!!! ask for segmentation in that case | |
532 | |
510 for (int n = 0; n < source.results.size(); ++n) { | 533 for (int n = 0; n < source.results.size(); ++n) { |
511 | 534 |
512 // This result spans source.results[n].time to | 535 // This result spans source.results[n].time to |
513 // source.results[n].time + source.results[n].duration. | 536 // source.results[n].time + source.results[n].duration. |
514 // We need to dispose it into segments appropriately | 537 // We need to dispose it into segments appropriately |
515 | 538 |
516 RealTime resultStart = source.results[n].time; | 539 RealTime resultStart = source.results[n].time; |
517 RealTime resultEnd = resultStart + source.results[n].duration; | 540 RealTime resultEnd = resultStart + source.results[n].duration; |
541 | |
542 std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl; | |
518 | 543 |
519 RealTime segmentStart = RealTime::zeroTime; | 544 RealTime segmentStart = RealTime::zeroTime; |
520 RealTime segmentEnd = resultEnd - RealTime(1, 0); | 545 RealTime segmentEnd = resultEnd - RealTime(1, 0); |
521 | 546 |
522 while (segmentEnd < resultEnd) { | 547 while (segmentEnd < resultEnd) { |
586 void | 611 void |
587 PluginSummarisingAdapter::Impl::reduce() | 612 PluginSummarisingAdapter::Impl::reduce() |
588 { | 613 { |
589 accumulateFinalDurations(); | 614 accumulateFinalDurations(); |
590 | 615 |
591 RealTime segmentStart = RealTime::zeroTime; //!!! | 616 for (OutputSegmentAccumulatorMap::iterator i = |
592 | 617 m_segmentedAccumulators.begin(); |
593 for (OutputAccumulatorMap::iterator i = m_accumulators.begin(); | 618 i != m_segmentedAccumulators.end(); ++i) { |
594 i != m_accumulators.end(); ++i) { | |
595 | 619 |
596 int output = i->first; | 620 int output = i->first; |
597 OutputAccumulator &accumulator = i->second; | 621 SegmentAccumulatorMap &segments = i->second; |
598 | 622 |
599 int sz = accumulator.results.size(); | 623 for (SegmentAccumulatorMap::iterator j = segments.begin(); |
600 | 624 j != segments.end(); ++j) { |
601 double totalDuration = 0.0; | 625 |
602 //!!! is this right? | 626 RealTime segmentStart = j->first; |
603 if (sz > 0) { | 627 OutputAccumulator &accumulator = j->second; |
604 totalDuration = toSec(accumulator.results[sz-1].time + | 628 |
605 accumulator.results[sz-1].duration); | 629 int sz = accumulator.results.size(); |
630 | |
631 double totalDuration = 0.0; | |
632 //!!! is this right? | |
633 if (sz > 0) { | |
634 totalDuration = toSec(accumulator.results[sz-1].time + | |
635 accumulator.results[sz-1].duration); | |
636 } | |
637 | |
638 for (int bin = 0; bin < accumulator.bins; ++bin) { | |
639 | |
640 // work on all values over time for a single bin | |
641 | |
642 OutputBinSummary summary; | |
643 | |
644 summary.count = sz; | |
645 | |
646 summary.minimum = 0.f; | |
647 summary.maximum = 0.f; | |
648 | |
649 summary.median = 0.f; | |
650 summary.mode = 0.f; | |
651 summary.sum = 0.f; | |
652 summary.variance = 0.f; | |
653 | |
654 summary.median_c = 0.f; | |
655 summary.mode_c = 0.f; | |
656 summary.mean_c = 0.f; | |
657 summary.variance_c = 0.f; | |
658 | |
659 if (sz == 0) continue; | |
660 | |
661 std::vector<ValueDurationFloatPair> valvec; | |
662 | |
663 for (int k = 0; k < sz; ++k) { | |
664 while (accumulator.results[k].values.size() < | |
665 accumulator.bins) { | |
666 accumulator.results[k].values.push_back(0.f); | |
667 } | |
668 } | |
669 | |
670 for (int k = 0; k < sz; ++k) { | |
671 float value = accumulator.results[k].values[bin]; | |
672 valvec.push_back(ValueDurationFloatPair | |
673 (value, | |
674 toSec(accumulator.results[k].duration))); | |
675 } | |
676 | |
677 std::sort(valvec.begin(), valvec.end()); | |
678 | |
679 summary.minimum = valvec[0].value; | |
680 summary.maximum = valvec[sz-1].value; | |
681 | |
682 if (sz % 2 == 1) { | |
683 summary.median = valvec[sz/2].value; | |
684 } else { | |
685 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2; | |
686 } | |
687 | |
688 double duracc = 0.0; | |
689 summary.median_c = valvec[sz-1].value; | |
690 | |
691 for (int k = 0; k < sz; ++k) { | |
692 duracc += valvec[k].duration; | |
693 if (duracc > totalDuration/2) { | |
694 summary.median_c = valvec[k].value; | |
695 break; | |
696 } | |
697 } | |
698 | |
699 std::cerr << "median_c = " << summary.median_c << std::endl; | |
700 std::cerr << "median = " << summary.median << std::endl; | |
701 | |
702 std::map<float, int> distribution; | |
703 | |
704 for (int k = 0; k < sz; ++k) { | |
705 summary.sum += accumulator.results[k].values[bin]; | |
706 distribution[accumulator.results[k].values[bin]] += 1; | |
707 } | |
708 | |
709 int md = 0; | |
710 | |
711 for (std::map<float, int>::iterator di = distribution.begin(); | |
712 di != distribution.end(); ++di) { | |
713 if (di->second > md) { | |
714 md = di->second; | |
715 summary.mode = di->first; | |
716 } | |
717 } | |
718 | |
719 distribution.clear(); | |
720 | |
721 std::map<float, double> distribution_c; | |
722 | |
723 for (int k = 0; k < sz; ++k) { | |
724 distribution_c[accumulator.results[k].values[bin]] | |
725 += toSec(accumulator.results[k].duration); | |
726 } | |
727 | |
728 double mrd = 0.0; | |
729 | |
730 for (std::map<float, double>::iterator di = distribution_c.begin(); | |
731 di != distribution_c.end(); ++di) { | |
732 if (di->second > mrd) { | |
733 mrd = di->second; | |
734 summary.mode_c = di->first; | |
735 } | |
736 } | |
737 | |
738 distribution_c.clear(); | |
739 | |
740 if (totalDuration > 0.0) { | |
741 | |
742 double sum_c = 0.0; | |
743 | |
744 for (int k = 0; k < sz; ++k) { | |
745 double value = accumulator.results[k].values[bin] | |
746 * toSec(accumulator.results[k].duration); | |
747 sum_c += value; | |
748 } | |
749 | |
750 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = " | |
751 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl; | |
752 | |
753 summary.mean_c = sum_c / totalDuration; | |
754 | |
755 for (int k = 0; k < sz; ++k) { | |
756 double value = accumulator.results[k].values[bin] | |
757 * toSec(accumulator.results[k].duration); | |
758 summary.variance_c += | |
759 (value - summary.mean_c) * (value - summary.mean_c); | |
760 } | |
761 | |
762 summary.variance_c /= summary.count; | |
763 } | |
764 | |
765 float mean = summary.sum / summary.count; | |
766 | |
767 std::cerr << "mean = " << summary.sum << " / " << summary.count << " = " | |
768 << summary.sum / summary.count << std::endl; | |
769 | |
770 for (int k = 0; k < sz; ++k) { | |
771 float value = accumulator.results[k].values[bin]; | |
772 summary.variance += (value - mean) * (value - mean); | |
773 } | |
774 summary.variance /= summary.count; | |
775 | |
776 m_summaries[output][segmentStart][bin] = summary; | |
777 } | |
606 } | 778 } |
607 | 779 } |
608 for (int bin = 0; bin < accumulator.bins; ++bin) { | 780 |
609 | 781 m_segmentedAccumulators.clear(); |
610 // work on all values over time for a single bin | |
611 | |
612 OutputBinSummary summary; | |
613 | |
614 summary.count = sz; | |
615 | |
616 summary.minimum = 0.f; | |
617 summary.maximum = 0.f; | |
618 | |
619 summary.median = 0.f; | |
620 summary.mode = 0.f; | |
621 summary.sum = 0.f; | |
622 summary.variance = 0.f; | |
623 | |
624 summary.median_c = 0.f; | |
625 summary.mode_c = 0.f; | |
626 summary.mean_c = 0.f; | |
627 summary.variance_c = 0.f; | |
628 | |
629 if (sz == 0) continue; | |
630 | |
631 std::vector<ValueDurationFloatPair> valvec; | |
632 | |
633 for (int k = 0; k < sz; ++k) { | |
634 while (accumulator.results[k].values.size() < | |
635 accumulator.bins) { | |
636 accumulator.results[k].values.push_back(0.f); | |
637 } | |
638 } | |
639 | |
640 for (int k = 0; k < sz; ++k) { | |
641 float value = accumulator.results[k].values[bin]; | |
642 valvec.push_back(ValueDurationFloatPair | |
643 (value, | |
644 toSec(accumulator.results[k].duration))); | |
645 } | |
646 | |
647 std::sort(valvec.begin(), valvec.end()); | |
648 | |
649 summary.minimum = valvec[0].value; | |
650 summary.maximum = valvec[sz-1].value; | |
651 | |
652 if (sz % 2 == 1) { | |
653 summary.median = valvec[sz/2].value; | |
654 } else { | |
655 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2; | |
656 } | |
657 | |
658 double duracc = 0.0; | |
659 summary.median_c = valvec[sz-1].value; | |
660 | |
661 for (int k = 0; k < sz; ++k) { | |
662 duracc += valvec[k].duration; | |
663 if (duracc > totalDuration/2) { | |
664 summary.median_c = valvec[k].value; | |
665 break; | |
666 } | |
667 } | |
668 | |
669 std::cerr << "median_c = " << summary.median_c << std::endl; | |
670 std::cerr << "median = " << summary.median << std::endl; | |
671 | |
672 std::map<float, int> distribution; | |
673 | |
674 for (int k = 0; k < sz; ++k) { | |
675 summary.sum += accumulator.results[k].values[bin]; | |
676 distribution[accumulator.results[k].values[bin]] += 1; | |
677 } | |
678 | |
679 int md = 0; | |
680 | |
681 for (std::map<float, int>::iterator di = distribution.begin(); | |
682 di != distribution.end(); ++di) { | |
683 if (di->second > md) { | |
684 md = di->second; | |
685 summary.mode = di->first; | |
686 } | |
687 } | |
688 | |
689 distribution.clear(); | |
690 | |
691 std::map<float, double> distribution_c; | |
692 | |
693 for (int k = 0; k < sz; ++k) { | |
694 distribution_c[accumulator.results[k].values[bin]] | |
695 += toSec(accumulator.results[k].duration); | |
696 } | |
697 | |
698 double mrd = 0.0; | |
699 | |
700 for (std::map<float, double>::iterator di = distribution_c.begin(); | |
701 di != distribution_c.end(); ++di) { | |
702 if (di->second > mrd) { | |
703 mrd = di->second; | |
704 summary.mode_c = di->first; | |
705 } | |
706 } | |
707 | |
708 distribution_c.clear(); | |
709 | |
710 if (totalDuration > 0.0) { | |
711 | |
712 double sum_c = 0.0; | |
713 | |
714 for (int k = 0; k < sz; ++k) { | |
715 double value = accumulator.results[k].values[bin] | |
716 * toSec(accumulator.results[k].duration); | |
717 sum_c += value; | |
718 } | |
719 | |
720 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = " | |
721 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl; | |
722 | |
723 summary.mean_c = sum_c / totalDuration; | |
724 | |
725 for (int k = 0; k < sz; ++k) { | |
726 double value = accumulator.results[k].values[bin] | |
727 * toSec(accumulator.results[k].duration); | |
728 summary.variance_c += | |
729 (value - summary.mean_c) * (value - summary.mean_c); | |
730 } | |
731 | |
732 summary.variance_c /= summary.count; | |
733 } | |
734 | |
735 float mean = summary.sum / summary.count; | |
736 | |
737 std::cerr << "mean = " << summary.sum << " / " << summary.count << " = " | |
738 << summary.sum / summary.count << std::endl; | |
739 | |
740 for (int k = 0; k < sz; ++k) { | |
741 float value = accumulator.results[k].values[bin]; | |
742 summary.variance += (value - mean) * (value - mean); | |
743 } | |
744 summary.variance /= summary.count; | |
745 | |
746 m_summaries[output][segmentStart][bin] = summary; | |
747 } | |
748 } | |
749 | |
750 m_accumulators.clear(); | 782 m_accumulators.clear(); |
751 } | 783 } |
752 | 784 |
753 | 785 |
754 } | 786 } |