# HG changeset patch # User cannam # Date 1220541564 0 # Node ID cd16cbf80c878517e76d69eedfddea415b99894c # Parent 9a58bd07aa4d3c47d1b0173fb0c2cb8d39b24b4a * More work on continuous-time averaging diff -r 9a58bd07aa4d -r cd16cbf80c87 vamp-sdk/hostext/PluginSummarisingAdapter.cpp --- a/vamp-sdk/hostext/PluginSummarisingAdapter.cpp Wed Sep 03 15:59:09 2008 +0000 +++ b/vamp-sdk/hostext/PluginSummarisingAdapter.cpp Thu Sep 04 15:19:24 2008 +0000 @@ -63,6 +63,7 @@ protected: Plugin *m_plugin; + float m_inputSampleRate; SegmentBoundaries m_boundaries; @@ -157,7 +158,8 @@ } PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : - m_plugin(plugin) + m_plugin(plugin), + m_inputSampleRate(inputSampleRate) { } @@ -343,6 +345,28 @@ else m_prevDuration = RealTime::zeroTime; } +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() { @@ -354,22 +378,18 @@ int output = i->first; OutputAccumulator &accumulator = i->second; - RealTime totalDuration; - size_t dindex = 0; - - while (dindex < accumulator.durations.size()) { - totalDuration = totalDuration + accumulator.durations[dindex++]; + double totalDuration; + for (int k = 0; k < accumulator.durations.size(); ++k) { + totalDuration += toSec(accumulator.durations[k]); } - dindex = 0; - for (BinValueMap::iterator j = accumulator.values.begin(); j != accumulator.values.end(); ++j) { // work on all values over time for a single bin int bin = j->first; - ValueList &values = j->second; + const ValueList &values = j->second; const DurationList &durations = accumulator.durations; OutputBinSummary summary; @@ -391,24 +411,46 @@ if (summary.count == 0 || values.empty()) continue; - std::sort(values.begin(), values.end()); int sz = values.size(); if (sz != durations.size()) { - //!!! is this reasonable? std::cerr << "WARNING: sz " << sz << " != durations.size() " << durations.size() << std::endl; +// while (durations.size() < sz) { +// durations.push_back(RealTime::zeroTime); +// } +//!!! then what? } - summary.minimum = values[0]; - summary.maximum = values[sz-1]; + std::vector valvec; + + for (int k = 0; k < sz; ++k) { + valvec.push_back(ValueDurationFloatPair(values[k], + toSec(durations[k]))); + } + + std::sort(valvec.begin(), valvec.end()); + + summary.minimum = valvec[0].value; + summary.maximum = valvec[sz-1].value; if (sz % 2 == 1) { - summary.median = values[sz/2]; + summary.median = valvec[sz/2].value; } else { - summary.median = (values[sz/2] + values[sz/2 + 1]) / 2; + 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; + } + } + std::map distribution; for (int k = 0; k < sz; ++k) { @@ -431,16 +473,15 @@ //!!! we want to omit this bit if the features all have //!!! equal duration (and set mode_c equal to mode instead) - std::map distribution_c; + std::map distribution_c; for (int k = 0; k < sz; ++k) { - distribution_c[values[k]] = - distribution_c[values[k]] + durations[k]; + distribution_c[values[k]] += toSec(durations[k]); } - RealTime mrd = RealTime::zeroTime; + double mrd = 0.0; - for (std::map::iterator di = distribution_c.begin(); + for (std::map::iterator di = distribution_c.begin(); di != distribution_c.end(); ++di) { if (di->second > mrd) { mrd = di->second; @@ -450,7 +491,27 @@ distribution_c.clear(); - //!!! handle mean_c, median_c, variance_c + if (totalDuration > 0.0) { + + double sum_c = 0.0; + + for (int k = 0; k < sz; ++k) { + double value = values[k] * toSec(durations[k]); + sum_c += value; + } + + summary.mean_c = sum_c / totalDuration; + + for (int k = 0; k < sz; ++k) { + double value = values[k] * toSec(durations[k]); + summary.variance_c += + (value - summary.mean_c) * (value - summary.mean_c); + } + + summary.variance_c /= summary.count; + } + + //!!! still to handle: median_c float mean = summary.sum / summary.count;