summaryrefslogtreecommitdiff
path: root/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp')
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp952
1 files changed, 0 insertions, 952 deletions
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp
deleted file mode 100644
index e3547a3daa..0000000000
--- a/libs/vamp-sdk/src/vamp-hostsdk/PluginSummarisingAdapter.cpp
+++ /dev/null
@@ -1,952 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
-
-/*
- Vamp
-
- An API for audio analysis and feature extraction plugins.
-
- Centre for Digital Music, Queen Mary, University of London.
- Copyright 2006-2009 Chris Cannam and QMUL.
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use, copy,
- modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
- ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- Except as contained in this notice, the names of the Centre for
- Digital Music; Queen Mary, University of London; and Chris Cannam
- shall not be used in advertising or otherwise to promote the sale,
- use or other dealings in this Software without prior written
- authorization.
-*/
-
-#include "vamp-hostsdk/PluginSummarisingAdapter.h"
-
-#include <map>
-#include <algorithm>
-#include <cmath>
-#include <climits>
-
-//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1
-//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT 1
-
-_VAMP_SDK_HOSTSPACE_BEGIN(PluginSummarisingAdapter.cpp)
-
-namespace Vamp {
-
-namespace HostExt {
-
-class PluginSummarisingAdapter::Impl
-{
-public:
- Impl(Plugin *plugin, float inputSampleRate);
- ~Impl();
-
- bool initialise(size_t channels, size_t stepSize, size_t blockSize);
-
- void reset();
-
- FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
- FeatureSet getRemainingFeatures();
-
- void setSummarySegmentBoundaries(const SegmentBoundaries &);
-
- FeatureList getSummaryForOutput(int output,
- SummaryType type,
- AveragingMethod avg);
-
- FeatureSet getSummaryForAllOutputs(SummaryType type,
- AveragingMethod avg);
-
-protected:
- Plugin *m_plugin;
- float m_inputSampleRate;
- size_t m_stepSize;
- size_t m_blockSize;
-
- SegmentBoundaries m_boundaries;
-
- typedef std::vector<float> ValueList;
-
- struct Result { // smaller than Feature
- RealTime time;
- RealTime duration;
- ValueList values; // bin number -> value
- };
-
- typedef std::vector<Result> ResultList;
-
- struct OutputAccumulator {
- int bins;
- ResultList results;
- OutputAccumulator() : bins(0) { }
- };
-
- typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
- OutputAccumulatorMap m_accumulators; // output number -> accumulator
-
- typedef std::map<RealTime, OutputAccumulator> SegmentAccumulatorMap;
- typedef std::map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap;
- OutputSegmentAccumulatorMap m_segmentedAccumulators; // output -> segmented
-
- typedef std::map<int, RealTime> OutputTimestampMap;
- OutputTimestampMap m_prevTimestamps; // output number -> timestamp
- OutputTimestampMap m_prevDurations; // output number -> durations
-
- struct OutputBinSummary {
-
- int count;
-
- // extents
- double minimum;
- double maximum;
- double sum;
-
- // sample-average results
- double median;
- double mode;
- double variance;
-
- // continuous-time average results
- double median_c;
- double mode_c;
- double mean_c;
- double variance_c;
- };
-
- typedef std::map<int, OutputBinSummary> OutputSummary;
- typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
- typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
-
- OutputSummarySegmentMap m_summaries;
-
- bool m_reduced;
- RealTime m_endTime;
-
- void accumulate(const FeatureSet &fs, RealTime, bool final);
- void accumulate(int output, const Feature &f, RealTime, bool final);
- void accumulateFinalDurations();
- void findSegmentBounds(RealTime t, RealTime &start, RealTime &end);
- void segment();
- void reduce();
-
- std::string getSummaryLabel(SummaryType type, AveragingMethod avg);
-};
-
-static RealTime INVALID_DURATION(INT_MIN, INT_MIN);
-
-PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
- PluginWrapper(plugin)
-{
- m_impl = new Impl(plugin, m_inputSampleRate);
-}
-
-PluginSummarisingAdapter::~PluginSummarisingAdapter()
-{
- delete m_impl;
-}
-
-bool
-PluginSummarisingAdapter::initialise(size_t channels,
- size_t stepSize, size_t blockSize)
-{
- return
- PluginWrapper::initialise(channels, stepSize, blockSize) &&
- m_impl->initialise(channels, stepSize, blockSize);
-}
-
-void
-PluginSummarisingAdapter::reset()
-{
- m_impl->reset();
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
-{
- return m_impl->process(inputBuffers, timestamp);
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::getRemainingFeatures()
-{
- return m_impl->getRemainingFeatures();
-}
-
-void
-PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries &b)
-{
- m_impl->setSummarySegmentBoundaries(b);
-}
-
-Plugin::FeatureList
-PluginSummarisingAdapter::getSummaryForOutput(int output,
- SummaryType type,
- AveragingMethod avg)
-{
- return m_impl->getSummaryForOutput(output, type, avg);
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type,
- AveragingMethod avg)
-{
- return m_impl->getSummaryForAllOutputs(type, avg);
-}
-
-PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
- m_plugin(plugin),
- m_inputSampleRate(inputSampleRate),
- m_reduced(false)
-{
-}
-
-PluginSummarisingAdapter::Impl::~Impl()
-{
-}
-
-bool
-PluginSummarisingAdapter::Impl::initialise(size_t channels,
- size_t stepSize, size_t blockSize)
-{
- m_stepSize = stepSize;
- m_blockSize = blockSize;
- return true;
-}
-
-void
-PluginSummarisingAdapter::Impl::reset()
-{
- m_accumulators.clear();
- m_segmentedAccumulators.clear();
- m_prevTimestamps.clear();
- m_prevDurations.clear();
- m_summaries.clear();
- m_reduced = false;
- m_endTime = RealTime();
- m_plugin->reset();
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers,
- RealTime timestamp)
-{
- if (m_reduced) {
- std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
- }
- FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
- accumulate(fs, timestamp, false);
- m_endTime = timestamp +
- RealTime::frame2RealTime(m_stepSize, int(m_inputSampleRate + 0.5));
- return fs;
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::Impl::getRemainingFeatures()
-{
- if (m_reduced) {
- std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
- }
- FeatureSet fs = m_plugin->getRemainingFeatures();
- accumulate(fs, m_endTime, true);
- return fs;
-}
-
-void
-PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundaries &b)
-{
- m_boundaries = b;
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "PluginSummarisingAdapter::setSummarySegmentBoundaries: boundaries are:" << std::endl;
- for (SegmentBoundaries::const_iterator i = m_boundaries.begin();
- i != m_boundaries.end(); ++i) {
- std::cerr << *i << " ";
- }
- std::cerr << std::endl;
-#endif
-}
-
-Plugin::FeatureList
-PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
- SummaryType type,
- AveragingMethod avg)
-{
- if (!m_reduced) {
- accumulateFinalDurations();
- segment();
- reduce();
- m_reduced = true;
- }
-
- bool continuous = (avg == ContinuousTimeAverage);
-
- FeatureList fl;
- for (SummarySegmentMap::const_iterator i = m_summaries[output].begin();
- i != m_summaries[output].end(); ++i) {
-
- Feature f;
-
- f.hasTimestamp = true;
- f.timestamp = i->first;
-
- f.hasDuration = true;
- SummarySegmentMap::const_iterator ii = i;
- if (++ii == m_summaries[output].end()) {
- f.duration = m_endTime - f.timestamp;
- } else {
- f.duration = ii->first - f.timestamp;
- }
-
- f.label = getSummaryLabel(type, avg);
-
- for (OutputSummary::const_iterator j = i->second.begin();
- j != i->second.end(); ++j) {
-
- // these will be ordered by bin number, and no bin numbers
- // will be missing except at the end (because of the way
- // the accumulators were initially filled in accumulate())
-
- const OutputBinSummary &summary = j->second;
- double result = 0.f;
-
- switch (type) {
-
- case Minimum:
- result = summary.minimum;
- break;
-
- case Maximum:
- result = summary.maximum;
- break;
-
- case Mean:
- if (continuous) {
- result = summary.mean_c;
- } else if (summary.count) {
- result = summary.sum / summary.count;
- }
- break;
-
- case Median:
- if (continuous) result = summary.median_c;
- else result = summary.median;
- break;
-
- case Mode:
- if (continuous) result = summary.mode_c;
- else result = summary.mode;
- break;
-
- case Sum:
- result = summary.sum;
- break;
-
- case Variance:
- if (continuous) result = summary.variance_c;
- else result = summary.variance;
- break;
-
- case StandardDeviation:
- if (continuous) result = sqrtf(summary.variance_c);
- else result = sqrtf(summary.variance);
- break;
-
- case Count:
- result = summary.count;
- break;
-
- case UnknownSummaryType:
- break;
-
- default:
- break;
- }
-
- f.values.push_back(result);
- }
-
- fl.push_back(f);
- }
- return fl;
-}
-
-Plugin::FeatureSet
-PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
- AveragingMethod avg)
-{
- if (!m_reduced) {
- accumulateFinalDurations();
- segment();
- reduce();
- m_reduced = true;
- }
-
- FeatureSet fs;
- for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin();
- i != m_summaries.end(); ++i) {
- fs[i->first] = getSummaryForOutput(i->first, type, avg);
- }
- return fs;
-}
-
-void
-PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
- RealTime timestamp,
- bool final)
-{
- for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
- for (FeatureList::const_iterator j = i->second.begin();
- j != i->second.end(); ++j) {
- if (j->hasTimestamp) {
- accumulate(i->first, *j, j->timestamp, final);
- } else {
- //!!! is this correct?
- accumulate(i->first, *j, timestamp, final);
- }
- }
- }
-}
-
-std::string
-PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type,
- AveragingMethod avg)
-{
- std::string label;
- std::string avglabel;
-
- if (avg == SampleAverage) avglabel = ", sample average";
- else avglabel = ", continuous-time average";
-
- switch (type) {
- case Minimum: label = "(minimum value)"; break;
- case Maximum: label = "(maximum value)"; break;
- case Mean: label = "(mean value" + avglabel + ")"; break;
- case Median: label = "(median value" + avglabel + ")"; break;
- case Mode: label = "(modal value" + avglabel + ")"; break;
- case Sum: label = "(sum)"; break;
- case Variance: label = "(variance" + avglabel + ")"; break;
- case StandardDeviation: label = "(standard deviation" + avglabel + ")"; break;
- case Count: label = "(count)"; break;
- case UnknownSummaryType: label = "(unknown summary)"; break;
- }
-
- return label;
-}
-
-void
-PluginSummarisingAdapter::Impl::accumulate(int output,
- const Feature &f,
- RealTime timestamp,
- bool final)
-{
- // What should happen if a feature's duration spans a segment
- // boundary? I think we probably want to chop it, and pretend
- // that it appears in both. A very long feature (e.g. key, if the
- // whole audio is in a single key) might span many or all
- // segments, and we want that to be reflected in the results
- // (e.g. it is the modal key in all of those segments, not just
- // the first). This is actually quite complicated to do.
-
- // If features spanning a boundary should be chopped, then we need
- // to have per-segment accumulators (and the feature value goes
- // into both -- with a separate phase to split the accumulator up
- // into segments).
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl;
-#endif
-
- // At each process step, accumulate() is called once for each
- // feature on each output within that process's returned feature
- // list, and with the timestamp passed in being that of the start
- // of the process block.
-
- // At the end (in getRemainingFeatures), accumulate() is called
- // once for each feature on each output within the feature list
- // returned by getRemainingFeatures, and with the timestamp being
- // the same as the last process block and final set to true.
-
- // (What if getRemainingFeatures doesn't return any features? We
- // still need to ensure that the final duration is written. Need
- // a separate function to close the durations.)
-
- // At each call, we pull out the value for the feature and stuff
- // it into the accumulator's appropriate values array; and we
- // calculate the duration for the _previous_ feature, or pull it
- // from the prevDurations array if the previous feature had a
- // duration in its structure, and stuff that into the
- // accumulator's appropriate durations array.
-
- if (m_prevDurations.find(output) != m_prevDurations.end()) {
-
- // Not the first time accumulate has been called for this
- // output -- there has been a previous feature
-
- RealTime prevDuration;
-
- // Note that m_prevDurations[output] only contains the
- // duration field that was contained in the previous feature.
- // If it didn't have an explicit duration,
- // m_prevDurations[output] should be INVALID_DURATION and we
- // will have to calculate the duration from the previous and
- // current timestamps.
-
- if (m_prevDurations[output] != INVALID_DURATION) {
- prevDuration = m_prevDurations[output];
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl;
-#endif
- } else {
- prevDuration = timestamp - m_prevTimestamps[output];
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "Previous duration from diff: " << timestamp << " - "
- << m_prevTimestamps[output] << std::endl;
-#endif
- }
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "output " << output << ": ";
- std::cerr << "Pushing previous duration as " << prevDuration << std::endl;
-#endif
-
- m_accumulators[output].results
- [m_accumulators[output].results.size() - 1]
- .duration = prevDuration;
- }
-
- if (f.hasDuration) m_prevDurations[output] = f.duration;
- else m_prevDurations[output] = INVALID_DURATION;
-
- m_prevTimestamps[output] = timestamp;
-
- if (f.hasDuration) {
- RealTime et = timestamp;
- et = et + f.duration;
- if (et > m_endTime) m_endTime = et;
- }
-
- Result result;
- result.time = timestamp;
- result.duration = INVALID_DURATION;
-
- if (int(f.values.size()) > m_accumulators[output].bins) {
- m_accumulators[output].bins = f.values.size();
- }
-
- for (int i = 0; i < int(f.values.size()); ++i) {
- result.values.push_back(f.values[i]);
- }
-
- m_accumulators[output].results.push_back(result);
-}
-
-void
-PluginSummarisingAdapter::Impl::accumulateFinalDurations()
-{
- for (OutputTimestampMap::iterator i = m_prevTimestamps.begin();
- i != m_prevTimestamps.end(); ++i) {
-
- int output = i->first;
-
- int acount = m_accumulators[output].results.size();
-
- if (acount == 0) continue;
-
- RealTime prevTimestamp = i->second;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "output " << output << ": ";
-#endif
-
- if (m_prevDurations.find(output) != m_prevDurations.end() &&
- m_prevDurations[output] != INVALID_DURATION) {
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl;
-#endif
-
- m_accumulators[output].results[acount - 1].duration =
- m_prevDurations[output];
-
- } else {
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "Pushing final duration from diff as " << m_endTime << " - " << m_prevTimestamps[output] << std::endl;
-#endif
-
- m_accumulators[output].results[acount - 1].duration =
- m_endTime - m_prevTimestamps[output];
- }
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "so duration for result no " << acount-1 << " is "
- << m_accumulators[output].results[acount-1].duration
- << std::endl;
-#endif
- }
-}
-
-void
-PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t,
- RealTime &start,
- RealTime &end)
-{
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "findSegmentBounds: t = " << t << std::endl;
-#endif
-
- SegmentBoundaries::const_iterator i = std::upper_bound
- (m_boundaries.begin(), m_boundaries.end(), t);
-
- start = RealTime::zeroTime;
- end = m_endTime;
-
- if (i != m_boundaries.end()) {
- end = *i;
- }
-
- if (i != m_boundaries.begin()) {
- start = *--i;
- }
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << std::endl;
-#endif
-}
-
-void
-PluginSummarisingAdapter::Impl::segment()
-{
- SegmentBoundaries::iterator boundaryitr = m_boundaries.begin();
- RealTime segmentStart = RealTime::zeroTime;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "segment: starting" << std::endl;
-#endif
-
- for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
- i != m_accumulators.end(); ++i) {
-
- int output = i->first;
- OutputAccumulator &source = i->second;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "segment: total results for output " << output << " = "
- << source.results.size() << std::endl;
-#endif
-
- // This is basically nonsense if the results have no values
- // (i.e. their times and counts are the only things of
- // interest)... but perhaps it's the user's problem if they
- // ask for segmentation (or any summary at all) in that case
-
- for (int n = 0; n < int(source.results.size()); ++n) {
-
- // This result spans source.results[n].time to
- // source.results[n].time + source.results[n].duration.
- // We need to dispose it into segments appropriately
-
- RealTime resultStart = source.results[n].time;
- RealTime resultEnd = resultStart + source.results[n].duration;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << std::endl;
-#endif
-
- RealTime segmentStart = RealTime::zeroTime;
- RealTime segmentEnd = resultEnd - RealTime(1, 0);
-
- RealTime prevSegmentStart = segmentStart - RealTime(1, 0);
-
- while (segmentEnd < resultEnd) {
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "segment end " << segmentEnd << " < result end "
- << resultEnd << " (with result start " << resultStart << ")" << std::endl;
-#endif
-
- findSegmentBounds(resultStart, segmentStart, segmentEnd);
-
- if (segmentStart == prevSegmentStart) {
- // This can happen when we reach the end of the
- // input, if a feature's end time overruns the
- // input audio end time
- break;
- }
- prevSegmentStart = segmentStart;
-
- RealTime chunkStart = resultStart;
- if (chunkStart < segmentStart) chunkStart = segmentStart;
-
- RealTime chunkEnd = resultEnd;
- if (chunkEnd > segmentEnd) chunkEnd = segmentEnd;
-
- m_segmentedAccumulators[output][segmentStart].bins = source.bins;
-
- Result chunk;
- chunk.time = chunkStart;
- chunk.duration = chunkEnd - chunkStart;
- chunk.values = source.results[n].values;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
- std::cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << std::endl;
-#endif
-
- m_segmentedAccumulators[output][segmentStart].results
- .push_back(chunk);
-
- resultStart = chunkEnd;
- }
- }
- }
-}
-
-struct ValueDurationFloatPair
-{
- float value;
- float duration;
-
- ValueDurationFloatPair() : value(0), duration(0) { }
- ValueDurationFloatPair(float v, float d) : value(v), duration(d) { }
- ValueDurationFloatPair &operator=(const ValueDurationFloatPair &p) {
- value = p.value;
- duration = p.duration;
- return *this;
- }
- bool operator<(const ValueDurationFloatPair &p) const {
- return value < p.value;
- }
-};
-
-static double toSec(const RealTime &r)
-{
- return r.sec + double(r.nsec) / 1000000000.0;
-}
-
-void
-PluginSummarisingAdapter::Impl::reduce()
-{
- for (OutputSegmentAccumulatorMap::iterator i =
- m_segmentedAccumulators.begin();
- i != m_segmentedAccumulators.end(); ++i) {
-
- int output = i->first;
- SegmentAccumulatorMap &segments = i->second;
-
- for (SegmentAccumulatorMap::iterator j = segments.begin();
- j != segments.end(); ++j) {
-
- RealTime segmentStart = j->first;
- OutputAccumulator &accumulator = j->second;
-
- int sz = accumulator.results.size();
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "reduce: segment starting at " << segmentStart
- << " on output " << output << " has " << sz << " result(s)" << std::endl;
-#endif
-
- double totalDuration = 0.0;
- //!!! is this right?
- if (sz > 0) {
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "last time = " << accumulator.results[sz-1].time
- << ", duration = " << accumulator.results[sz-1].duration
- << " (step = " << m_stepSize << ", block = " << m_blockSize << ")"
- << std::endl;
-#endif
- totalDuration = toSec((accumulator.results[sz-1].time +
- accumulator.results[sz-1].duration) -
- segmentStart);
- }
-
- for (int bin = 0; bin < accumulator.bins; ++bin) {
-
- // work on all values over time for a single bin
-
- OutputBinSummary summary;
-
- summary.count = sz;
-
- summary.minimum = 0.f;
- summary.maximum = 0.f;
-
- summary.median = 0.f;
- summary.mode = 0.f;
- summary.sum = 0.f;
- summary.variance = 0.f;
-
- summary.median_c = 0.f;
- summary.mode_c = 0.f;
- summary.mean_c = 0.f;
- summary.variance_c = 0.f;
-
- if (sz == 0) continue;
-
- std::vector<ValueDurationFloatPair> valvec;
-
- for (int k = 0; k < sz; ++k) {
- while (int(accumulator.results[k].values.size()) <
- accumulator.bins) {
- accumulator.results[k].values.push_back(0.f);
- }
- }
-
- for (int k = 0; k < sz; ++k) {
- float value = accumulator.results[k].values[bin];
- valvec.push_back(ValueDurationFloatPair
- (value,
- toSec(accumulator.results[k].duration)));
- }
-
- std::sort(valvec.begin(), valvec.end());
-
- summary.minimum = valvec[0].value;
- summary.maximum = valvec[sz-1].value;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "total duration = " << totalDuration << std::endl;
-#endif
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
-/*
- std::cerr << "value vector for medians:" << std::endl;
- for (int k = 0; k < sz; ++k) {
- std::cerr << "(" << valvec[k].value << "," << valvec[k].duration << ") ";
- }
- std::cerr << std::endl;
-*/
-#endif
-
- if (sz % 2 == 1) {
- summary.median = valvec[sz/2].value;
- } else {
- summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2;
- }
-
- double duracc = 0.0;
- summary.median_c = valvec[sz-1].value;
-
- for (int k = 0; k < sz; ++k) {
- duracc += valvec[k].duration;
- if (duracc > totalDuration/2) {
- summary.median_c = valvec[k].value;
- break;
- }
- }
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "median_c = " << summary.median_c << std::endl;
- std::cerr << "median = " << summary.median << std::endl;
-#endif
-
- std::map<float, int> distribution;
-
- for (int k = 0; k < sz; ++k) {
- summary.sum += accumulator.results[k].values[bin];
- distribution[accumulator.results[k].values[bin]] += 1;
- }
-
- int md = 0;
-
- for (std::map<float, int>::iterator di = distribution.begin();
- di != distribution.end(); ++di) {
- if (di->second > md) {
- md = di->second;
- summary.mode = di->first;
- }
- }
-
- distribution.clear();
-
- std::map<float, double> distribution_c;
-
- for (int k = 0; k < sz; ++k) {
- distribution_c[accumulator.results[k].values[bin]]
- += toSec(accumulator.results[k].duration);
- }
-
- double mrd = 0.0;
-
- for (std::map<float, double>::iterator di = distribution_c.begin();
- di != distribution_c.end(); ++di) {
- if (di->second > mrd) {
- mrd = di->second;
- summary.mode_c = di->first;
- }
- }
-
- distribution_c.clear();
-
- if (totalDuration > 0.0) {
-
- double sum_c = 0.0;
-
- for (int k = 0; k < sz; ++k) {
- double value = accumulator.results[k].values[bin]
- * toSec(accumulator.results[k].duration);
- sum_c += value;
- }
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
- << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl;
-#endif
-
- summary.mean_c = sum_c / totalDuration;
-
- for (int k = 0; k < sz; ++k) {
- double value = accumulator.results[k].values[bin];
-// * toSec(accumulator.results[k].duration);
- summary.variance_c +=
- (value - summary.mean_c) * (value - summary.mean_c)
- * toSec(accumulator.results[k].duration);
- }
-
-// summary.variance_c /= summary.count;
- summary.variance_c /= totalDuration;
- }
-
- double mean = summary.sum / summary.count;
-
-#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
- std::cerr << "mean = " << summary.sum << " / " << summary.count << " = "
- << summary.sum / summary.count << std::endl;
-#endif
-
- for (int k = 0; k < sz; ++k) {
- float value = accumulator.results[k].values[bin];
- summary.variance += (value - mean) * (value - mean);
- }
- summary.variance /= summary.count;
-
- m_summaries[output][segmentStart][bin] = summary;
- }
- }
- }
-
- m_segmentedAccumulators.clear();
- m_accumulators.clear();
-}
-
-
-}
-
-}
-
-_VAMP_SDK_HOSTSPACE_END(PluginSummarisingAdapter.cpp)
-