annotate vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 184:26c200c3fc42

* Fixes to summarisation (calculation of durations)
author cannam
date Wed, 10 Sep 2008 14:54:25 +0000
parents c053ababbf7e
children 701505ac170c
rev   line source
cannam@173 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@173 2
cannam@173 3 /*
cannam@173 4 Vamp
cannam@173 5
cannam@173 6 An API for audio analysis and feature extraction plugins.
cannam@173 7
cannam@173 8 Centre for Digital Music, Queen Mary, University of London.
cannam@173 9 Copyright 2006-2008 Chris Cannam and QMUL.
cannam@173 10
cannam@173 11 Permission is hereby granted, free of charge, to any person
cannam@173 12 obtaining a copy of this software and associated documentation
cannam@173 13 files (the "Software"), to deal in the Software without
cannam@173 14 restriction, including without limitation the rights to use, copy,
cannam@173 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@173 16 of the Software, and to permit persons to whom the Software is
cannam@173 17 furnished to do so, subject to the following conditions:
cannam@173 18
cannam@173 19 The above copyright notice and this permission notice shall be
cannam@173 20 included in all copies or substantial portions of the Software.
cannam@173 21
cannam@173 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@173 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@173 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@173 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@173 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@173 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@173 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@173 29
cannam@173 30 Except as contained in this notice, the names of the Centre for
cannam@173 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@173 32 shall not be used in advertising or otherwise to promote the sale,
cannam@173 33 use or other dealings in this Software without prior written
cannam@173 34 authorization.
cannam@173 35 */
cannam@173 36
cannam@173 37 #include "PluginSummarisingAdapter.h"
cannam@173 38
cannam@174 39 #include <map>
cannam@175 40 #include <cmath>
cannam@184 41 #include <climits>
cannam@174 42
cannam@173 43 namespace Vamp {
cannam@173 44
cannam@173 45 namespace HostExt {
cannam@173 46
cannam@173 47 class PluginSummarisingAdapter::Impl
cannam@173 48 {
cannam@173 49 public:
cannam@173 50 Impl(Plugin *plugin, float inputSampleRate);
cannam@173 51 ~Impl();
cannam@173 52
cannam@173 53 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@173 54 FeatureSet getRemainingFeatures();
cannam@173 55
cannam@173 56 void setSummarySegmentBoundaries(const SegmentBoundaries &);
cannam@173 57
cannam@180 58 FeatureList getSummaryForOutput(int output,
cannam@180 59 SummaryType type,
cannam@180 60 AveragingMethod avg);
cannam@180 61
cannam@180 62 FeatureSet getSummaryForAllOutputs(SummaryType type,
cannam@180 63 AveragingMethod avg);
cannam@173 64
cannam@173 65 protected:
cannam@174 66 Plugin *m_plugin;
cannam@181 67 float m_inputSampleRate;
cannam@174 68
cannam@173 69 SegmentBoundaries m_boundaries;
cannam@174 70
cannam@174 71 typedef std::vector<float> ValueList;
cannam@174 72 typedef std::map<int, ValueList> BinValueMap;
cannam@180 73 typedef std::vector<RealTime> DurationList;
cannam@174 74
cannam@174 75 struct OutputAccumulator {
cannam@174 76 int count;
cannam@180 77 BinValueMap values; // bin number -> values ordered by time
cannam@180 78 DurationList durations;
cannam@180 79 OutputAccumulator() : count(0), values(), durations() { }
cannam@174 80 };
cannam@174 81
cannam@174 82 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
cannam@180 83 OutputAccumulatorMap m_accumulators; // output number -> accumulator
cannam@180 84
cannam@180 85 typedef std::map<int, RealTime> OutputTimestampMap;
cannam@180 86 OutputTimestampMap m_prevTimestamps; // output number -> timestamp
cannam@183 87 OutputTimestampMap m_prevDurations; // output number -> durations
cannam@174 88
cannam@174 89 struct OutputBinSummary {
cannam@180 90
cannam@180 91 int count;
cannam@180 92
cannam@180 93 // extents
cannam@174 94 float minimum;
cannam@174 95 float maximum;
cannam@180 96 float sum;
cannam@180 97
cannam@180 98 // sample-average results
cannam@174 99 float median;
cannam@174 100 float mode;
cannam@174 101 float variance;
cannam@180 102
cannam@180 103 // continuous-time average results
cannam@180 104 float median_c;
cannam@180 105 float mode_c;
cannam@180 106 float mean_c;
cannam@180 107 float variance_c;
cannam@174 108 };
cannam@174 109
cannam@174 110 typedef std::map<int, OutputBinSummary> OutputSummary;
cannam@174 111 typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
cannam@174 112 typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
cannam@174 113
cannam@174 114 OutputSummarySegmentMap m_summaries;
cannam@174 115
cannam@183 116 bool m_reduced;
cannam@174 117 RealTime m_lastTimestamp;
cannam@174 118
cannam@180 119 void accumulate(const FeatureSet &fs, RealTime, bool final);
cannam@180 120 void accumulate(int output, const Feature &f, RealTime, bool final);
cannam@184 121 void accumulateFinalDurations();
cannam@174 122 void reduce();
cannam@173 123 };
cannam@184 124
cannam@184 125 static RealTime INVALID_DURATION(INT_MIN, INT_MIN);
cannam@173 126
cannam@173 127 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
cannam@173 128 PluginWrapper(plugin)
cannam@173 129 {
cannam@173 130 m_impl = new Impl(plugin, m_inputSampleRate);
cannam@173 131 }
cannam@173 132
cannam@173 133 PluginSummarisingAdapter::~PluginSummarisingAdapter()
cannam@173 134 {
cannam@173 135 delete m_impl;
cannam@173 136 }
cannam@173 137
cannam@173 138 Plugin::FeatureSet
cannam@173 139 PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@173 140 {
cannam@173 141 return m_impl->process(inputBuffers, timestamp);
cannam@173 142 }
cannam@173 143
cannam@174 144 Plugin::FeatureSet
cannam@174 145 PluginSummarisingAdapter::getRemainingFeatures()
cannam@174 146 {
cannam@174 147 return m_impl->getRemainingFeatures();
cannam@174 148 }
cannam@174 149
cannam@175 150 Plugin::FeatureList
cannam@180 151 PluginSummarisingAdapter::getSummaryForOutput(int output,
cannam@180 152 SummaryType type,
cannam@180 153 AveragingMethod avg)
cannam@175 154 {
cannam@180 155 return m_impl->getSummaryForOutput(output, type, avg);
cannam@176 156 }
cannam@176 157
cannam@176 158 Plugin::FeatureSet
cannam@180 159 PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type,
cannam@180 160 AveragingMethod avg)
cannam@176 161 {
cannam@180 162 return m_impl->getSummaryForAllOutputs(type, avg);
cannam@175 163 }
cannam@173 164
cannam@173 165 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@181 166 m_plugin(plugin),
cannam@183 167 m_inputSampleRate(inputSampleRate),
cannam@183 168 m_reduced(false)
cannam@173 169 {
cannam@173 170 }
cannam@173 171
cannam@173 172 PluginSummarisingAdapter::Impl::~Impl()
cannam@173 173 {
cannam@173 174 }
cannam@173 175
cannam@174 176 Plugin::FeatureSet
cannam@174 177 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp)
cannam@174 178 {
cannam@183 179 if (m_reduced) {
cannam@183 180 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
cannam@183 181 }
cannam@174 182 FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
cannam@180 183 accumulate(fs, timestamp, false);
cannam@174 184 m_lastTimestamp = timestamp;
cannam@174 185 return fs;
cannam@174 186 }
cannam@174 187
cannam@174 188 Plugin::FeatureSet
cannam@174 189 PluginSummarisingAdapter::Impl::getRemainingFeatures()
cannam@174 190 {
cannam@183 191 if (m_reduced) {
cannam@183 192 std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
cannam@183 193 }
cannam@174 194 FeatureSet fs = m_plugin->getRemainingFeatures();
cannam@180 195 accumulate(fs, m_lastTimestamp, true);
cannam@174 196 return fs;
cannam@174 197 }
cannam@174 198
cannam@175 199 Plugin::FeatureList
cannam@180 200 PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
cannam@180 201 SummaryType type,
cannam@180 202 AveragingMethod avg)
cannam@175 203 {
cannam@183 204 if (!m_reduced) reduce();
cannam@183 205
cannam@180 206 bool continuous = (avg == ContinuousTimeAverage);
cannam@180 207
cannam@175 208 FeatureList fl;
cannam@175 209 for (SummarySegmentMap::const_iterator i = m_summaries[output].begin();
cannam@175 210 i != m_summaries[output].end(); ++i) {
cannam@177 211
cannam@175 212 Feature f;
cannam@175 213 f.hasTimestamp = true;
cannam@175 214 f.timestamp = i->first;
cannam@175 215 f.hasDuration = false;
cannam@177 216
cannam@175 217 for (OutputSummary::const_iterator j = i->second.begin();
cannam@175 218 j != i->second.end(); ++j) {
cannam@175 219
cannam@175 220 // these will be ordered by bin number, and no bin numbers
cannam@175 221 // will be missing except at the end (because of the way
cannam@175 222 // the accumulators were initially filled in accumulate())
cannam@175 223
cannam@175 224 const OutputBinSummary &summary = j->second;
cannam@175 225 float result = 0.f;
cannam@175 226
cannam@175 227 switch (type) {
cannam@175 228
cannam@175 229 case Minimum:
cannam@175 230 result = summary.minimum;
cannam@175 231 break;
cannam@175 232
cannam@175 233 case Maximum:
cannam@175 234 result = summary.maximum;
cannam@175 235 break;
cannam@175 236
cannam@175 237 case Mean:
cannam@180 238 if (continuous) {
cannam@180 239 result = summary.mean_c;
cannam@180 240 } else if (summary.count) {
cannam@175 241 result = summary.sum / summary.count;
cannam@175 242 }
cannam@175 243 break;
cannam@175 244
cannam@175 245 case Median:
cannam@180 246 if (continuous) result = summary.median_c;
cannam@180 247 else result = summary.median;
cannam@175 248 break;
cannam@175 249
cannam@175 250 case Mode:
cannam@180 251 if (continuous) result = summary.mode_c;
cannam@180 252 else result = summary.mode;
cannam@175 253 break;
cannam@175 254
cannam@175 255 case Sum:
cannam@175 256 result = summary.sum;
cannam@175 257 break;
cannam@175 258
cannam@175 259 case Variance:
cannam@180 260 if (continuous) result = summary.variance_c;
cannam@180 261 else result = summary.variance;
cannam@175 262 break;
cannam@175 263
cannam@175 264 case StandardDeviation:
cannam@180 265 if (continuous) result = sqrtf(summary.variance_c);
cannam@180 266 else result = sqrtf(summary.variance);
cannam@175 267 break;
cannam@175 268
cannam@175 269 case Count:
cannam@175 270 result = summary.count;
cannam@175 271 break;
cannam@180 272
cannam@180 273 default:
cannam@180 274 break;
cannam@175 275 }
cannam@177 276
cannam@177 277 f.values.push_back(result);
cannam@175 278 }
cannam@175 279
cannam@175 280 fl.push_back(f);
cannam@175 281 }
cannam@175 282 return fl;
cannam@175 283 }
cannam@175 284
cannam@176 285 Plugin::FeatureSet
cannam@180 286 PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
cannam@180 287 AveragingMethod avg)
cannam@176 288 {
cannam@183 289 if (!m_reduced) reduce();
cannam@183 290
cannam@176 291 FeatureSet fs;
cannam@176 292 for (OutputSummarySegmentMap::const_iterator i = m_summaries.begin();
cannam@176 293 i != m_summaries.end(); ++i) {
cannam@180 294 fs[i->first] = getSummaryForOutput(i->first, type, avg);
cannam@176 295 }
cannam@176 296 return fs;
cannam@176 297 }
cannam@176 298
cannam@174 299 void
cannam@174 300 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
cannam@180 301 RealTime timestamp,
cannam@180 302 bool final)
cannam@174 303 {
cannam@174 304 for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
cannam@174 305 for (FeatureList::const_iterator j = i->second.begin();
cannam@174 306 j != i->second.end(); ++j) {
cannam@182 307 if (j->hasTimestamp) {
cannam@182 308 accumulate(i->first, *j, j->timestamp, final);
cannam@182 309 } else {
cannam@182 310 //!!! is this correct?
cannam@182 311 accumulate(i->first, *j, timestamp, final);
cannam@182 312 }
cannam@174 313 }
cannam@174 314 }
cannam@174 315 }
cannam@174 316
cannam@174 317 void
cannam@174 318 PluginSummarisingAdapter::Impl::accumulate(int output,
cannam@174 319 const Feature &f,
cannam@180 320 RealTime timestamp,
cannam@180 321 bool final)
cannam@174 322 {
cannam@180 323 //!!! to do: use timestamp to determine which segment we're on
cannam@180 324
cannam@174 325 m_accumulators[output].count++;
cannam@180 326
cannam@184 327 std::cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << std::endl;
cannam@182 328
cannam@184 329 // At each process step, accumulate() is called once for each
cannam@184 330 // feature on each output within that process's returned feature
cannam@184 331 // list, and with the timestamp passed in being that of the start
cannam@184 332 // of the process block.
cannam@182 333
cannam@184 334 // At the end (in getRemainingFeatures), accumulate() is called
cannam@184 335 // once for each feature on each output within the feature list
cannam@184 336 // returned by getRemainingFeatures, and with the timestamp being
cannam@184 337 // the same as the last process block and final set to true.
cannam@184 338
cannam@184 339 // (What if getRemainingFeatures doesn't return any features? We
cannam@184 340 // still need to ensure that the final duration is written. Need
cannam@184 341 // a separate function to close the durations.)
cannam@184 342
cannam@184 343 // At each call, we pull out the value for the feature and stuff
cannam@184 344 // it into the accumulator's appropriate values array; and we
cannam@184 345 // calculate the duration for the _previous_ feature, or pull it
cannam@184 346 // from the prevDurations array if the previous feature had a
cannam@184 347 // duration in its structure, and stuff that into the
cannam@184 348 // accumulator's appropriate durations array.
cannam@184 349
cannam@184 350 if (m_prevDurations.find(output) != m_prevDurations.end()) {
cannam@184 351
cannam@184 352 // Not the first time accumulate has been called for this
cannam@184 353 // output -- there has been a previous feature
cannam@184 354
cannam@184 355 RealTime prevDuration;
cannam@184 356
cannam@184 357 // Note that m_prevDurations[output] only contains the
cannam@184 358 // duration field that was contained in the previous feature.
cannam@184 359 // If it didn't have an explicit duration,
cannam@184 360 // m_prevDurations[output] should be INVALID_DURATION and we
cannam@184 361 // will have to calculate the duration from the previous and
cannam@184 362 // current timestamps.
cannam@184 363
cannam@184 364 if (m_prevDurations[output] != INVALID_DURATION) {
cannam@184 365 prevDuration = m_prevDurations[output];
cannam@184 366 std::cerr << "Previous duration from previous feature: " << prevDuration << std::endl;
cannam@184 367 } else {
cannam@184 368 prevDuration = timestamp - m_prevTimestamps[output];
cannam@184 369 std::cerr << "Previous duration from diff: " << timestamp << " - "
cannam@184 370 << m_prevTimestamps[output] << std::endl;
cannam@180 371 }
cannam@184 372
cannam@184 373 std::cerr << "output " << output << ": ";
cannam@184 374
cannam@184 375 std::cerr << "Pushing previous duration as " << prevDuration << std::endl;
cannam@184 376 m_accumulators[output].durations.push_back(prevDuration);
cannam@180 377 }
cannam@180 378
cannam@184 379 if (f.hasDuration) m_prevDurations[output] = f.duration;
cannam@184 380 else m_prevDurations[output] = INVALID_DURATION;
cannam@184 381
cannam@180 382 m_prevTimestamps[output] = timestamp;
cannam@184 383 if (timestamp > m_lastTimestamp) m_lastTimestamp = timestamp;
cannam@180 384
cannam@174 385 for (int i = 0; i < int(f.values.size()); ++i) {
cannam@174 386 m_accumulators[output].values[i].push_back(f.values[i]);
cannam@174 387 }
cannam@184 388 }
cannam@180 389
cannam@184 390 void
cannam@184 391 PluginSummarisingAdapter::Impl::accumulateFinalDurations()
cannam@184 392 {
cannam@184 393 for (OutputTimestampMap::iterator i = m_prevTimestamps.begin();
cannam@184 394 i != m_prevTimestamps.end(); ++i) {
cannam@184 395
cannam@184 396 int output = i->first;
cannam@184 397 RealTime prevTimestamp = i->second;
cannam@184 398
cannam@184 399 std::cerr << "output " << output << ": ";
cannam@184 400
cannam@184 401 if (m_prevDurations.find(output) != m_prevDurations.end() &&
cannam@184 402 m_prevDurations[output] != INVALID_DURATION) {
cannam@184 403
cannam@184 404 std::cerr << "Pushing final duration from feature as " << m_prevDurations[output] << std::endl;
cannam@184 405
cannam@184 406 m_accumulators[output].durations.push_back(m_prevDurations[output]);
cannam@184 407
cannam@184 408 } else {
cannam@184 409
cannam@184 410 std::cerr << "Pushing final duration from diff as " << m_lastTimestamp << " - " << m_prevTimestamps[output] << std::endl;
cannam@184 411
cannam@184 412 m_accumulators[output].durations.push_back
cannam@184 413 (m_lastTimestamp - m_prevTimestamps[output]);
cannam@184 414 }
cannam@180 415 }
cannam@174 416 }
cannam@174 417
cannam@181 418 struct ValueDurationFloatPair
cannam@181 419 {
cannam@181 420 float value;
cannam@181 421 float duration;
cannam@181 422
cannam@181 423 ValueDurationFloatPair() : value(0), duration(0) { }
cannam@181 424 ValueDurationFloatPair(float v, float d) : value(v), duration(d) { }
cannam@181 425 ValueDurationFloatPair &operator=(const ValueDurationFloatPair &p) {
cannam@181 426 value = p.value;
cannam@181 427 duration = p.duration;
cannam@181 428 return *this;
cannam@181 429 }
cannam@181 430 bool operator<(const ValueDurationFloatPair &p) const {
cannam@181 431 return value < p.value;
cannam@181 432 }
cannam@181 433 };
cannam@181 434
cannam@181 435 static double toSec(const RealTime &r)
cannam@181 436 {
cannam@181 437 return r.sec + double(r.nsec) / 1000000000.0;
cannam@181 438 }
cannam@181 439
cannam@174 440 void
cannam@174 441 PluginSummarisingAdapter::Impl::reduce()
cannam@174 442 {
cannam@184 443 accumulateFinalDurations();
cannam@184 444
cannam@174 445 RealTime segmentStart = RealTime::zeroTime; //!!!
cannam@174 446
cannam@174 447 for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
cannam@174 448 i != m_accumulators.end(); ++i) {
cannam@174 449
cannam@174 450 int output = i->first;
cannam@174 451 OutputAccumulator &accumulator = i->second;
cannam@174 452
cannam@182 453 double totalDuration = 0.0;
cannam@181 454 for (int k = 0; k < accumulator.durations.size(); ++k) {
cannam@181 455 totalDuration += toSec(accumulator.durations[k]);
cannam@180 456 }
cannam@180 457
cannam@174 458 for (BinValueMap::iterator j = accumulator.values.begin();
cannam@174 459 j != accumulator.values.end(); ++j) {
cannam@174 460
cannam@180 461 // work on all values over time for a single bin
cannam@180 462
cannam@174 463 int bin = j->first;
cannam@181 464 const ValueList &values = j->second;
cannam@180 465 const DurationList &durations = accumulator.durations;
cannam@174 466
cannam@174 467 OutputBinSummary summary;
cannam@180 468
cannam@180 469 summary.count = accumulator.count;
cannam@180 470
cannam@174 471 summary.minimum = 0.f;
cannam@174 472 summary.maximum = 0.f;
cannam@180 473
cannam@174 474 summary.median = 0.f;
cannam@174 475 summary.mode = 0.f;
cannam@174 476 summary.sum = 0.f;
cannam@174 477 summary.variance = 0.f;
cannam@180 478
cannam@180 479 summary.median_c = 0.f;
cannam@180 480 summary.mode_c = 0.f;
cannam@180 481 summary.mean_c = 0.f;
cannam@180 482 summary.variance_c = 0.f;
cannam@180 483
cannam@174 484 if (summary.count == 0 || values.empty()) continue;
cannam@174 485
cannam@174 486 int sz = values.size();
cannam@174 487
cannam@180 488 if (sz != durations.size()) {
cannam@180 489 std::cerr << "WARNING: sz " << sz << " != durations.size() "
cannam@180 490 << durations.size() << std::endl;
cannam@181 491 // while (durations.size() < sz) {
cannam@181 492 // durations.push_back(RealTime::zeroTime);
cannam@181 493 // }
cannam@181 494 //!!! then what?
cannam@180 495 }
cannam@180 496
cannam@181 497 std::vector<ValueDurationFloatPair> valvec;
cannam@181 498
cannam@181 499 for (int k = 0; k < sz; ++k) {
cannam@181 500 valvec.push_back(ValueDurationFloatPair(values[k],
cannam@181 501 toSec(durations[k])));
cannam@181 502 }
cannam@181 503
cannam@181 504 std::sort(valvec.begin(), valvec.end());
cannam@181 505
cannam@181 506 summary.minimum = valvec[0].value;
cannam@181 507 summary.maximum = valvec[sz-1].value;
cannam@174 508
cannam@174 509 if (sz % 2 == 1) {
cannam@181 510 summary.median = valvec[sz/2].value;
cannam@174 511 } else {
cannam@181 512 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2;
cannam@174 513 }
cannam@181 514
cannam@181 515 double duracc = 0.0;
cannam@181 516 summary.median_c = valvec[sz-1].value;
cannam@174 517
cannam@181 518 for (int k = 0; k < sz; ++k) {
cannam@181 519 duracc += valvec[k].duration;
cannam@181 520 if (duracc > totalDuration/2) {
cannam@181 521 summary.median_c = valvec[k].value;
cannam@181 522 break;
cannam@181 523 }
cannam@181 524 }
cannam@181 525
cannam@174 526 std::map<float, int> distribution;
cannam@174 527
cannam@174 528 for (int k = 0; k < sz; ++k) {
cannam@174 529 summary.sum += values[k];
cannam@180 530 distribution[values[k]] += 1;
cannam@174 531 }
cannam@174 532
cannam@174 533 int md = 0;
cannam@174 534
cannam@174 535 for (std::map<float, int>::iterator di = distribution.begin();
cannam@174 536 di != distribution.end(); ++di) {
cannam@174 537 if (di->second > md) {
cannam@174 538 md = di->second;
cannam@174 539 summary.mode = di->first;
cannam@174 540 }
cannam@174 541 }
cannam@174 542
cannam@174 543 distribution.clear();
cannam@174 544
cannam@180 545 //!!! we want to omit this bit if the features all have
cannam@180 546 //!!! equal duration (and set mode_c equal to mode instead)
cannam@180 547
cannam@181 548 std::map<float, double> distribution_c;
cannam@180 549
cannam@180 550 for (int k = 0; k < sz; ++k) {
cannam@181 551 distribution_c[values[k]] += toSec(durations[k]);
cannam@180 552 }
cannam@180 553
cannam@181 554 double mrd = 0.0;
cannam@180 555
cannam@181 556 for (std::map<float, double>::iterator di = distribution_c.begin();
cannam@180 557 di != distribution_c.end(); ++di) {
cannam@180 558 if (di->second > mrd) {
cannam@180 559 mrd = di->second;
cannam@180 560 summary.mode_c = di->first;
cannam@180 561 }
cannam@180 562 }
cannam@180 563
cannam@180 564 distribution_c.clear();
cannam@180 565
cannam@181 566 if (totalDuration > 0.0) {
cannam@181 567
cannam@181 568 double sum_c = 0.0;
cannam@181 569
cannam@181 570 for (int k = 0; k < sz; ++k) {
cannam@181 571 double value = values[k] * toSec(durations[k]);
cannam@181 572 sum_c += value;
cannam@181 573 }
cannam@182 574
cannam@182 575 std::cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
cannam@184 576 << sum_c / totalDuration << " (sz = " << sz << ")" << std::endl;
cannam@181 577
cannam@181 578 summary.mean_c = sum_c / totalDuration;
cannam@181 579
cannam@181 580 for (int k = 0; k < sz; ++k) {
cannam@181 581 double value = values[k] * toSec(durations[k]);
cannam@181 582 summary.variance_c +=
cannam@181 583 (value - summary.mean_c) * (value - summary.mean_c);
cannam@181 584 }
cannam@181 585
cannam@181 586 summary.variance_c /= summary.count;
cannam@181 587 }
cannam@181 588
cannam@181 589 //!!! still to handle: median_c
cannam@180 590
cannam@174 591 float mean = summary.sum / summary.count;
cannam@174 592
cannam@182 593 std::cerr << "mean = " << summary.sum << " / " << summary.count << " = "
cannam@182 594 << summary.sum / summary.count << std::endl;
cannam@182 595
cannam@174 596 for (int k = 0; k < sz; ++k) {
cannam@174 597 summary.variance += (values[k] - mean) * (values[k] - mean);
cannam@174 598 }
cannam@174 599 summary.variance /= summary.count;
cannam@174 600
cannam@174 601 m_summaries[output][segmentStart][bin] = summary;
cannam@174 602 }
cannam@174 603 }
cannam@175 604
cannam@175 605 m_accumulators.clear();
cannam@183 606 m_reduced = true;
cannam@174 607 }
cannam@174 608
cannam@174 609
cannam@174 610 }
cannam@174 611
cannam@174 612 }
cannam@174 613