1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
6 An API for audio analysis and feature extraction plugins.
8 Centre for Digital Music, Queen Mary, University of London.
9 Copyright 2006-2009 Chris Cannam and QMUL.
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 Except as contained in this notice, the names of the Centre for
31 Digital Music; Queen Mary, University of London; and Chris Cannam
32 shall not be used in advertising or otherwise to promote the sale,
33 use or other dealings in this Software without prior written
37 #include "vamp-hostsdk/PluginSummarisingAdapter.h"
44 //#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1
45 //#define DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT 1
47 _VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter
.cpp
)
53 class PluginSummarisingAdapter::Impl
56 Impl(Plugin
*plugin
, float inputSampleRate
);
59 bool initialise(size_t channels
, size_t stepSize
, size_t blockSize
);
63 FeatureSet
process(const float *const *inputBuffers
, RealTime timestamp
);
64 FeatureSet
getRemainingFeatures();
66 void setSummarySegmentBoundaries(const SegmentBoundaries
&);
68 FeatureList
getSummaryForOutput(int output
,
72 FeatureSet
getSummaryForAllOutputs(SummaryType type
,
77 float m_inputSampleRate
;
81 SegmentBoundaries m_boundaries
;
83 typedef std::vector
<float> ValueList
;
85 struct Result
{ // smaller than Feature
88 ValueList values
; // bin number -> value
91 typedef std::vector
<Result
> ResultList
;
93 struct OutputAccumulator
{
96 OutputAccumulator() : bins(0) { }
99 typedef std::map
<int, OutputAccumulator
> OutputAccumulatorMap
;
100 OutputAccumulatorMap m_accumulators
; // output number -> accumulator
102 typedef std::map
<RealTime
, OutputAccumulator
> SegmentAccumulatorMap
;
103 typedef std::map
<int, SegmentAccumulatorMap
> OutputSegmentAccumulatorMap
;
104 OutputSegmentAccumulatorMap m_segmentedAccumulators
; // output -> segmented
106 typedef std::map
<int, RealTime
> OutputTimestampMap
;
107 OutputTimestampMap m_prevTimestamps
; // output number -> timestamp
108 OutputTimestampMap m_prevDurations
; // output number -> durations
110 struct OutputBinSummary
{
119 // sample-average results
124 // continuous-time average results
131 typedef std::map
<int, OutputBinSummary
> OutputSummary
;
132 typedef std::map
<RealTime
, OutputSummary
> SummarySegmentMap
;
133 typedef std::map
<int, SummarySegmentMap
> OutputSummarySegmentMap
;
135 OutputSummarySegmentMap m_summaries
;
140 void accumulate(const FeatureSet
&fs
, RealTime
, bool final
);
141 void accumulate(int output
, const Feature
&f
, RealTime
, bool final
);
142 void accumulateFinalDurations();
143 void findSegmentBounds(RealTime t
, RealTime
&start
, RealTime
&end
);
147 std::string
getSummaryLabel(SummaryType type
, AveragingMethod avg
);
150 static RealTime
INVALID_DURATION(INT_MIN
, INT_MIN
);
152 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin
*plugin
) :
153 PluginWrapper(plugin
)
155 m_impl
= new Impl(plugin
, m_inputSampleRate
);
158 PluginSummarisingAdapter::~PluginSummarisingAdapter()
164 PluginSummarisingAdapter::initialise(size_t channels
,
165 size_t stepSize
, size_t blockSize
)
168 PluginWrapper::initialise(channels
, stepSize
, blockSize
) &&
169 m_impl
->initialise(channels
, stepSize
, blockSize
);
173 PluginSummarisingAdapter::reset()
179 PluginSummarisingAdapter::process(const float *const *inputBuffers
, RealTime timestamp
)
181 return m_impl
->process(inputBuffers
, timestamp
);
185 PluginSummarisingAdapter::getRemainingFeatures()
187 return m_impl
->getRemainingFeatures();
191 PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries
&b
)
193 m_impl
->setSummarySegmentBoundaries(b
);
197 PluginSummarisingAdapter::getSummaryForOutput(int output
,
201 return m_impl
->getSummaryForOutput(output
, type
, avg
);
205 PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type
,
208 return m_impl
->getSummaryForAllOutputs(type
, avg
);
211 PluginSummarisingAdapter::Impl::Impl(Plugin
*plugin
, float inputSampleRate
) :
213 m_inputSampleRate(inputSampleRate
),
218 PluginSummarisingAdapter::Impl::~Impl()
223 PluginSummarisingAdapter::Impl::initialise(size_t channels
,
224 size_t stepSize
, size_t blockSize
)
226 m_stepSize
= stepSize
;
227 m_blockSize
= blockSize
;
232 PluginSummarisingAdapter::Impl::reset()
234 m_accumulators
.clear();
235 m_segmentedAccumulators
.clear();
236 m_prevTimestamps
.clear();
237 m_prevDurations
.clear();
240 m_endTime
= RealTime();
245 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers
,
249 std::cerr
<< "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl
;
251 FeatureSet fs
= m_plugin
->process(inputBuffers
, timestamp
);
252 accumulate(fs
, timestamp
, false);
253 m_endTime
= timestamp
+
254 RealTime::frame2RealTime(m_stepSize
, int(m_inputSampleRate
+ 0.5));
259 PluginSummarisingAdapter::Impl::getRemainingFeatures()
262 std::cerr
<< "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl
;
264 FeatureSet fs
= m_plugin
->getRemainingFeatures();
265 accumulate(fs
, m_endTime
, true);
270 PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries
&b
)
273 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
274 std::cerr
<< "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl
;
275 for (SegmentBoundaries::const_iterator i
= m_boundaries
.begin();
276 i
!= m_boundaries
.end(); ++i
) {
277 std::cerr
<< *i
<< " ";
279 std::cerr
<< std::endl
;
284 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output
,
289 accumulateFinalDurations();
295 bool continuous
= (avg
== ContinuousTimeAverage
);
298 for (SummarySegmentMap::const_iterator i
= m_summaries
[output
].begin();
299 i
!= m_summaries
[output
].end(); ++i
) {
303 f
.hasTimestamp
= true;
304 f
.timestamp
= i
->first
;
306 f
.hasDuration
= true;
307 SummarySegmentMap::const_iterator ii
= i
;
308 if (++ii
== m_summaries
[output
].end()) {
309 f
.duration
= m_endTime
- f
.timestamp
;
311 f
.duration
= ii
->first
- f
.timestamp
;
314 f
.label
= getSummaryLabel(type
, avg
);
316 for (OutputSummary::const_iterator j
= i
->second
.begin();
317 j
!= i
->second
.end(); ++j
) {
319 // these will be ordered by bin number, and no bin numbers
320 // will be missing except at the end (because of the way
321 // the accumulators were initially filled in accumulate())
323 const OutputBinSummary
&summary
= j
->second
;
329 result
= summary
.minimum
;
333 result
= summary
.maximum
;
338 result
= summary
.mean_c
;
339 } else if (summary
.count
) {
340 result
= summary
.sum
/ summary
.count
;
345 if (continuous
) result
= summary
.median_c
;
346 else result
= summary
.median
;
350 if (continuous
) result
= summary
.mode_c
;
351 else result
= summary
.mode
;
355 result
= summary
.sum
;
359 if (continuous
) result
= summary
.variance_c
;
360 else result
= summary
.variance
;
363 case StandardDeviation
:
364 if (continuous
) result
= sqrtf(summary
.variance_c
);
365 else result
= sqrtf(summary
.variance
);
369 result
= summary
.count
;
372 case UnknownSummaryType
:
379 f
.values
.push_back(result
);
388 PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type
,
392 accumulateFinalDurations();
399 for (OutputSummarySegmentMap::const_iterator i
= m_summaries
.begin();
400 i
!= m_summaries
.end(); ++i
) {
401 fs
[i
->first
] = getSummaryForOutput(i
->first
, type
, avg
);
407 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet
&fs
,
411 for (FeatureSet::const_iterator i
= fs
.begin(); i
!= fs
.end(); ++i
) {
412 for (FeatureList::const_iterator j
= i
->second
.begin();
413 j
!= i
->second
.end(); ++j
) {
414 if (j
->hasTimestamp
) {
415 accumulate(i
->first
, *j
, j
->timestamp
, final
);
417 //!!! is this correct?
418 accumulate(i
->first
, *j
, timestamp
, final
);
425 PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type
,
429 std::string avglabel
;
431 if (avg
== SampleAverage
) avglabel
= ", sample average";
432 else avglabel
= ", continuous-time average";
435 case Minimum
: label
= "(minimum value)"; break;
436 case Maximum
: label
= "(maximum value)"; break;
437 case Mean
: label
= "(mean value" + avglabel
+ ")"; break;
438 case Median
: label
= "(median value" + avglabel
+ ")"; break;
439 case Mode
: label
= "(modal value" + avglabel
+ ")"; break;
440 case Sum
: label
= "(sum)"; break;
441 case Variance
: label
= "(variance" + avglabel
+ ")"; break;
442 case StandardDeviation
: label
= "(standard deviation" + avglabel
+ ")"; break;
443 case Count
: label
= "(count)"; break;
444 case UnknownSummaryType
: label
= "(unknown summary)"; break;
451 PluginSummarisingAdapter::Impl::accumulate(int output
,
456 // What should happen if a feature's duration spans a segment
457 // boundary? I think we probably want to chop it, and pretend
458 // that it appears in both. A very long feature (e.g. key, if the
459 // whole audio is in a single key) might span many or all
460 // segments, and we want that to be reflected in the results
461 // (e.g. it is the modal key in all of those segments, not just
462 // the first). This is actually quite complicated to do.
464 // If features spanning a boundary should be chopped, then we need
465 // to have per-segment accumulators (and the feature value goes
466 // into both -- with a separate phase to split the accumulator up
469 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
470 std::cerr
<< "output " << output
<< ": timestamp " << timestamp
<< ", prev timestamp " << m_prevTimestamps
[output
] << ", final " << final
<< std::endl
;
473 // At each process step, accumulate() is called once for each
474 // feature on each output within that process's returned feature
475 // list, and with the timestamp passed in being that of the start
476 // of the process block.
478 // At the end (in getRemainingFeatures), accumulate() is called
479 // once for each feature on each output within the feature list
480 // returned by getRemainingFeatures, and with the timestamp being
481 // the same as the last process block and final set to true.
483 // (What if getRemainingFeatures doesn't return any features? We
484 // still need to ensure that the final duration is written. Need
485 // a separate function to close the durations.)
487 // At each call, we pull out the value for the feature and stuff
488 // it into the accumulator's appropriate values array; and we
489 // calculate the duration for the _previous_ feature, or pull it
490 // from the prevDurations array if the previous feature had a
491 // duration in its structure, and stuff that into the
492 // accumulator's appropriate durations array.
494 if (m_prevDurations
.find(output
) != m_prevDurations
.end()) {
496 // Not the first time accumulate has been called for this
497 // output -- there has been a previous feature
499 RealTime prevDuration
;
501 // Note that m_prevDurations[output] only contains the
502 // duration field that was contained in the previous feature.
503 // If it didn't have an explicit duration,
504 // m_prevDurations[output] should be INVALID_DURATION and we
505 // will have to calculate the duration from the previous and
506 // current timestamps.
508 if (m_prevDurations
[output
] != INVALID_DURATION
) {
509 prevDuration
= m_prevDurations
[output
];
510 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
511 std::cerr
<< "Previous duration from previous feature: " << prevDuration
<< std::endl
;
514 prevDuration
= timestamp
- m_prevTimestamps
[output
];
515 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
516 std::cerr
<< "Previous duration from diff: " << timestamp
<< " - "
517 << m_prevTimestamps
[output
] << std::endl
;
521 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
522 std::cerr
<< "output " << output
<< ": ";
523 std::cerr
<< "Pushing previous duration as " << prevDuration
<< std::endl
;
526 m_accumulators
[output
].results
527 [m_accumulators
[output
].results
.size() - 1]
528 .duration
= prevDuration
;
531 if (f
.hasDuration
) m_prevDurations
[output
] = f
.duration
;
532 else m_prevDurations
[output
] = INVALID_DURATION
;
534 m_prevTimestamps
[output
] = timestamp
;
537 RealTime et
= timestamp
;
538 et
= et
+ f
.duration
;
539 if (et
> m_endTime
) m_endTime
= et
;
543 result
.time
= timestamp
;
544 result
.duration
= INVALID_DURATION
;
546 if (int(f
.values
.size()) > m_accumulators
[output
].bins
) {
547 m_accumulators
[output
].bins
= f
.values
.size();
550 for (int i
= 0; i
< int(f
.values
.size()); ++i
) {
551 result
.values
.push_back(f
.values
[i
]);
554 m_accumulators
[output
].results
.push_back(result
);
558 PluginSummarisingAdapter::Impl::accumulateFinalDurations()
560 for (OutputTimestampMap::iterator i
= m_prevTimestamps
.begin();
561 i
!= m_prevTimestamps
.end(); ++i
) {
563 int output
= i
->first
;
565 int acount
= m_accumulators
[output
].results
.size();
567 if (acount
== 0) continue;
569 RealTime prevTimestamp
= i
->second
;
571 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
572 std::cerr
<< "output " << output
<< ": ";
575 if (m_prevDurations
.find(output
) != m_prevDurations
.end() &&
576 m_prevDurations
[output
] != INVALID_DURATION
) {
578 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
579 std::cerr
<< "Pushing final duration from feature as " << m_prevDurations
[output
] << std::endl
;
582 m_accumulators
[output
].results
[acount
- 1].duration
=
583 m_prevDurations
[output
];
587 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
588 std::cerr
<< "Pushing final duration from diff as " << m_endTime
<< " - " << m_prevTimestamps
[output
] << std::endl
;
591 m_accumulators
[output
].results
[acount
- 1].duration
=
592 m_endTime
- m_prevTimestamps
[output
];
595 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
596 std::cerr
<< "so duration for result no " << acount
-1 << " is "
597 << m_accumulators
[output
].results
[acount
-1].duration
604 PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t
,
608 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
609 std::cerr
<< "findSegmentBounds: t = " << t
<< std::endl
;
612 SegmentBoundaries::const_iterator i
= std::upper_bound
613 (m_boundaries
.begin(), m_boundaries
.end(), t
);
615 start
= RealTime::zeroTime
;
618 if (i
!= m_boundaries
.end()) {
622 if (i
!= m_boundaries
.begin()) {
626 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
627 std::cerr
<< "findSegmentBounds: " << t
<< " is in segment " << start
<< " -> " << end
<< std::endl
;
632 PluginSummarisingAdapter::Impl::segment()
634 SegmentBoundaries::iterator boundaryitr
= m_boundaries
.begin();
635 RealTime segmentStart
= RealTime::zeroTime
;
637 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
638 std::cerr
<< "segment: starting" << std::endl
;
641 for (OutputAccumulatorMap::iterator i
= m_accumulators
.begin();
642 i
!= m_accumulators
.end(); ++i
) {
644 int output
= i
->first
;
645 OutputAccumulator
&source
= i
->second
;
647 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
648 std::cerr
<< "segment: total results for output " << output
<< " = "
649 << source
.results
.size() << std::endl
;
652 // This is basically nonsense if the results have no values
653 // (i.e. their times and counts are the only things of
654 // interest)... but perhaps it's the user's problem if they
655 // ask for segmentation (or any summary at all) in that case
657 for (int n
= 0; n
< int(source
.results
.size()); ++n
) {
659 // This result spans source.results[n].time to
660 // source.results[n].time + source.results[n].duration.
661 // We need to dispose it into segments appropriately
663 RealTime resultStart
= source
.results
[n
].time
;
664 RealTime resultEnd
= resultStart
+ source
.results
[n
].duration
;
666 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
667 std::cerr
<< "output: " << output
<< ", result start = " << resultStart
<< ", end = " << resultEnd
<< std::endl
;
670 RealTime segmentStart
= RealTime::zeroTime
;
671 RealTime segmentEnd
= resultEnd
- RealTime(1, 0);
673 RealTime prevSegmentStart
= segmentStart
- RealTime(1, 0);
675 while (segmentEnd
< resultEnd
) {
677 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
678 std::cerr
<< "segment end " << segmentEnd
<< " < result end "
679 << resultEnd
<< " (with result start " << resultStart
<< ")" << std::endl
;
682 findSegmentBounds(resultStart
, segmentStart
, segmentEnd
);
684 if (segmentStart
== prevSegmentStart
) {
685 // This can happen when we reach the end of the
686 // input, if a feature's end time overruns the
687 // input audio end time
690 prevSegmentStart
= segmentStart
;
692 RealTime chunkStart
= resultStart
;
693 if (chunkStart
< segmentStart
) chunkStart
= segmentStart
;
695 RealTime chunkEnd
= resultEnd
;
696 if (chunkEnd
> segmentEnd
) chunkEnd
= segmentEnd
;
698 m_segmentedAccumulators
[output
][segmentStart
].bins
= source
.bins
;
701 chunk
.time
= chunkStart
;
702 chunk
.duration
= chunkEnd
- chunkStart
;
703 chunk
.values
= source
.results
[n
].values
;
705 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
706 std::cerr
<< "chunk for segment " << segmentStart
<< ": from " << chunk
.time
<< ", duration " << chunk
.duration
<< std::endl
;
709 m_segmentedAccumulators
[output
][segmentStart
].results
712 resultStart
= chunkEnd
;
718 struct ValueDurationFloatPair
723 ValueDurationFloatPair() : value(0), duration(0) { }
724 ValueDurationFloatPair(float v
, float d
) : value(v
), duration(d
) { }
725 ValueDurationFloatPair
&operator=(const ValueDurationFloatPair
&p
) {
727 duration
= p
.duration
;
730 bool operator<(const ValueDurationFloatPair
&p
) const {
731 return value
< p
.value
;
735 static double toSec(const RealTime
&r
)
737 return r
.sec
+ double(r
.nsec
) / 1000000000.0;
741 PluginSummarisingAdapter::Impl::reduce()
743 for (OutputSegmentAccumulatorMap::iterator i
=
744 m_segmentedAccumulators
.begin();
745 i
!= m_segmentedAccumulators
.end(); ++i
) {
747 int output
= i
->first
;
748 SegmentAccumulatorMap
&segments
= i
->second
;
750 for (SegmentAccumulatorMap::iterator j
= segments
.begin();
751 j
!= segments
.end(); ++j
) {
753 RealTime segmentStart
= j
->first
;
754 OutputAccumulator
&accumulator
= j
->second
;
756 int sz
= accumulator
.results
.size();
758 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
759 std::cerr
<< "reduce: segment starting at " << segmentStart
760 << " on output " << output
<< " has " << sz
<< " result(s)" << std::endl
;
763 double totalDuration
= 0.0;
766 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
767 std::cerr
<< "last time = " << accumulator
.results
[sz
-1].time
768 << ", duration = " << accumulator
.results
[sz
-1].duration
769 << " (step = " << m_stepSize
<< ", block = " << m_blockSize
<< ")"
772 totalDuration
= toSec((accumulator
.results
[sz
-1].time
+
773 accumulator
.results
[sz
-1].duration
) -
777 for (int bin
= 0; bin
< accumulator
.bins
; ++bin
) {
779 // work on all values over time for a single bin
781 OutputBinSummary summary
;
785 summary
.minimum
= 0.f
;
786 summary
.maximum
= 0.f
;
788 summary
.median
= 0.f
;
791 summary
.variance
= 0.f
;
793 summary
.median_c
= 0.f
;
794 summary
.mode_c
= 0.f
;
795 summary
.mean_c
= 0.f
;
796 summary
.variance_c
= 0.f
;
798 if (sz
== 0) continue;
800 std::vector
<ValueDurationFloatPair
> valvec
;
802 for (int k
= 0; k
< sz
; ++k
) {
803 while (int(accumulator
.results
[k
].values
.size()) <
805 accumulator
.results
[k
].values
.push_back(0.f
);
809 for (int k
= 0; k
< sz
; ++k
) {
810 float value
= accumulator
.results
[k
].values
[bin
];
811 valvec
.push_back(ValueDurationFloatPair
813 toSec(accumulator
.results
[k
].duration
)));
816 std::sort(valvec
.begin(), valvec
.end());
818 summary
.minimum
= valvec
[0].value
;
819 summary
.maximum
= valvec
[sz
-1].value
;
821 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
822 std::cerr
<< "total duration = " << totalDuration
<< std::endl
;
825 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
827 std::cerr << "value vector for medians:" << std::endl;
828 for (int k = 0; k < sz; ++k) {
829 std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") ";
831 std::cerr << std::endl;
836 summary
.median
= valvec
[sz
/2].value
;
838 summary
.median
= (valvec
[sz
/2].value
+ valvec
[sz
/2 + 1].value
) / 2;
842 summary
.median_c
= valvec
[sz
-1].value
;
844 for (int k
= 0; k
< sz
; ++k
) {
845 duracc
+= valvec
[k
].duration
;
846 if (duracc
> totalDuration
/2) {
847 summary
.median_c
= valvec
[k
].value
;
852 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
853 std::cerr
<< "median_c = " << summary
.median_c
<< std::endl
;
854 std::cerr
<< "median = " << summary
.median
<< std::endl
;
857 std::map
<float, int> distribution
;
859 for (int k
= 0; k
< sz
; ++k
) {
860 summary
.sum
+= accumulator
.results
[k
].values
[bin
];
861 distribution
[accumulator
.results
[k
].values
[bin
]] += 1;
866 for (std::map
<float, int>::iterator di
= distribution
.begin();
867 di
!= distribution
.end(); ++di
) {
868 if (di
->second
> md
) {
870 summary
.mode
= di
->first
;
874 distribution
.clear();
876 std::map
<float, double> distribution_c
;
878 for (int k
= 0; k
< sz
; ++k
) {
879 distribution_c
[accumulator
.results
[k
].values
[bin
]]
880 += toSec(accumulator
.results
[k
].duration
);
885 for (std::map
<float, double>::iterator di
= distribution_c
.begin();
886 di
!= distribution_c
.end(); ++di
) {
887 if (di
->second
> mrd
) {
889 summary
.mode_c
= di
->first
;
893 distribution_c
.clear();
895 if (totalDuration
> 0.0) {
899 for (int k
= 0; k
< sz
; ++k
) {
900 double value
= accumulator
.results
[k
].values
[bin
]
901 * toSec(accumulator
.results
[k
].duration
);
905 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
906 std::cerr
<< "mean_c = " << sum_c
<< " / " << totalDuration
<< " = "
907 << sum_c
/ totalDuration
<< " (sz = " << sz
<< ")" << std::endl
;
910 summary
.mean_c
= sum_c
/ totalDuration
;
912 for (int k
= 0; k
< sz
; ++k
) {
913 double value
= accumulator
.results
[k
].values
[bin
];
914 // * toSec(accumulator.results[k].duration);
915 summary
.variance_c
+=
916 (value
- summary
.mean_c
) * (value
- summary
.mean_c
)
917 * toSec(accumulator
.results
[k
].duration
);
920 // summary.variance_c /= summary.count;
921 summary
.variance_c
/= totalDuration
;
924 double mean
= summary
.sum
/ summary
.count
;
926 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
927 std::cerr
<< "mean = " << summary
.sum
<< " / " << summary
.count
<< " = "
928 << summary
.sum
/ summary
.count
<< std::endl
;
931 for (int k
= 0; k
< sz
; ++k
) {
932 float value
= accumulator
.results
[k
].values
[bin
];
933 summary
.variance
+= (value
- mean
) * (value
- mean
);
935 summary
.variance
/= summary
.count
;
937 m_summaries
[output
][segmentStart
][bin
] = summary
;
942 m_segmentedAccumulators
.clear();
943 m_accumulators
.clear();
951 _VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter
.cpp
)