comparison vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 181:cd16cbf80c87

* More work on continuous-time averaging
author cannam
date Thu, 04 Sep 2008 15:19:24 +0000
parents 9a58bd07aa4d
children 3fcac0f3afdc
comparison
equal deleted inserted replaced
180:9a58bd07aa4d 181:cd16cbf80c87
61 FeatureSet getSummaryForAllOutputs(SummaryType type, 61 FeatureSet getSummaryForAllOutputs(SummaryType type,
62 AveragingMethod avg); 62 AveragingMethod avg);
63 63
64 protected: 64 protected:
65 Plugin *m_plugin; 65 Plugin *m_plugin;
66 float m_inputSampleRate;
66 67
67 SegmentBoundaries m_boundaries; 68 SegmentBoundaries m_boundaries;
68 69
69 typedef std::vector<float> ValueList; 70 typedef std::vector<float> ValueList;
70 typedef std::map<int, ValueList> BinValueMap; 71 typedef std::map<int, ValueList> BinValueMap;
155 { 156 {
156 return m_impl->getSummaryForAllOutputs(type, avg); 157 return m_impl->getSummaryForAllOutputs(type, avg);
157 } 158 }
158 159
159 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : 160 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
160 m_plugin(plugin) 161 m_plugin(plugin),
162 m_inputSampleRate(inputSampleRate)
161 { 163 {
162 } 164 }
163 165
164 PluginSummarisingAdapter::Impl::~Impl() 166 PluginSummarisingAdapter::Impl::~Impl()
165 { 167 {
341 343
342 if (f.hasDuration) m_prevDuration = f.duration; 344 if (f.hasDuration) m_prevDuration = f.duration;
343 else m_prevDuration = RealTime::zeroTime; 345 else m_prevDuration = RealTime::zeroTime;
344 } 346 }
345 347
348 struct ValueDurationFloatPair
349 {
350 float value;
351 float duration;
352
353 ValueDurationFloatPair() : value(0), duration(0) { }
354 ValueDurationFloatPair(float v, float d) : value(v), duration(d) { }
355 ValueDurationFloatPair &operator=(const ValueDurationFloatPair &p) {
356 value = p.value;
357 duration = p.duration;
358 return *this;
359 }
360 bool operator<(const ValueDurationFloatPair &p) const {
361 return value < p.value;
362 }
363 };
364
365 static double toSec(const RealTime &r)
366 {
367 return r.sec + double(r.nsec) / 1000000000.0;
368 }
369
346 void 370 void
347 PluginSummarisingAdapter::Impl::reduce() 371 PluginSummarisingAdapter::Impl::reduce()
348 { 372 {
349 RealTime segmentStart = RealTime::zeroTime; //!!! 373 RealTime segmentStart = RealTime::zeroTime; //!!!
350 374
352 i != m_accumulators.end(); ++i) { 376 i != m_accumulators.end(); ++i) {
353 377
354 int output = i->first; 378 int output = i->first;
355 OutputAccumulator &accumulator = i->second; 379 OutputAccumulator &accumulator = i->second;
356 380
357 RealTime totalDuration; 381 double totalDuration;
358 size_t dindex = 0; 382 for (int k = 0; k < accumulator.durations.size(); ++k) {
359 383 totalDuration += toSec(accumulator.durations[k]);
360 while (dindex < accumulator.durations.size()) {
361 totalDuration = totalDuration + accumulator.durations[dindex++];
362 } 384 }
363
364 dindex = 0;
365 385
366 for (BinValueMap::iterator j = accumulator.values.begin(); 386 for (BinValueMap::iterator j = accumulator.values.begin();
367 j != accumulator.values.end(); ++j) { 387 j != accumulator.values.end(); ++j) {
368 388
369 // work on all values over time for a single bin 389 // work on all values over time for a single bin
370 390
371 int bin = j->first; 391 int bin = j->first;
372 ValueList &values = j->second; 392 const ValueList &values = j->second;
373 const DurationList &durations = accumulator.durations; 393 const DurationList &durations = accumulator.durations;
374 394
375 OutputBinSummary summary; 395 OutputBinSummary summary;
376 396
377 summary.count = accumulator.count; 397 summary.count = accumulator.count;
389 summary.mean_c = 0.f; 409 summary.mean_c = 0.f;
390 summary.variance_c = 0.f; 410 summary.variance_c = 0.f;
391 411
392 if (summary.count == 0 || values.empty()) continue; 412 if (summary.count == 0 || values.empty()) continue;
393 413
394 std::sort(values.begin(), values.end());
395 int sz = values.size(); 414 int sz = values.size();
396 415
397 if (sz != durations.size()) { 416 if (sz != durations.size()) {
398 //!!! is this reasonable?
399 std::cerr << "WARNING: sz " << sz << " != durations.size() " 417 std::cerr << "WARNING: sz " << sz << " != durations.size() "
400 << durations.size() << std::endl; 418 << durations.size() << std::endl;
401 } 419 // while (durations.size() < sz) {
402 420 // durations.push_back(RealTime::zeroTime);
403 summary.minimum = values[0]; 421 // }
404 summary.maximum = values[sz-1]; 422 //!!! then what?
423 }
424
425 std::vector<ValueDurationFloatPair> valvec;
426
427 for (int k = 0; k < sz; ++k) {
428 valvec.push_back(ValueDurationFloatPair(values[k],
429 toSec(durations[k])));
430 }
431
432 std::sort(valvec.begin(), valvec.end());
433
434 summary.minimum = valvec[0].value;
435 summary.maximum = valvec[sz-1].value;
405 436
406 if (sz % 2 == 1) { 437 if (sz % 2 == 1) {
407 summary.median = values[sz/2]; 438 summary.median = valvec[sz/2].value;
408 } else { 439 } else {
409 summary.median = (values[sz/2] + values[sz/2 + 1]) / 2; 440 summary.median = (valvec[sz/2].value + valvec[sz/2 + 1].value) / 2;
410 } 441 }
411 442
443 double duracc = 0.0;
444 summary.median_c = valvec[sz-1].value;
445
446 for (int k = 0; k < sz; ++k) {
447 duracc += valvec[k].duration;
448 if (duracc > totalDuration/2) {
449 summary.median_c = valvec[k].value;
450 break;
451 }
452 }
453
412 std::map<float, int> distribution; 454 std::map<float, int> distribution;
413 455
414 for (int k = 0; k < sz; ++k) { 456 for (int k = 0; k < sz; ++k) {
415 summary.sum += values[k]; 457 summary.sum += values[k];
416 distribution[values[k]] += 1; 458 distribution[values[k]] += 1;
429 distribution.clear(); 471 distribution.clear();
430 472
431 //!!! we want to omit this bit if the features all have 473 //!!! we want to omit this bit if the features all have
432 //!!! equal duration (and set mode_c equal to mode instead) 474 //!!! equal duration (and set mode_c equal to mode instead)
433 475
434 std::map<float, RealTime> distribution_c; 476 std::map<float, double> distribution_c;
435 477
436 for (int k = 0; k < sz; ++k) { 478 for (int k = 0; k < sz; ++k) {
437 distribution_c[values[k]] = 479 distribution_c[values[k]] += toSec(durations[k]);
438 distribution_c[values[k]] + durations[k]; 480 }
439 } 481
440 482 double mrd = 0.0;
441 RealTime mrd = RealTime::zeroTime; 483
442 484 for (std::map<float, double>::iterator di = distribution_c.begin();
443 for (std::map<float, RealTime>::iterator di = distribution_c.begin();
444 di != distribution_c.end(); ++di) { 485 di != distribution_c.end(); ++di) {
445 if (di->second > mrd) { 486 if (di->second > mrd) {
446 mrd = di->second; 487 mrd = di->second;
447 summary.mode_c = di->first; 488 summary.mode_c = di->first;
448 } 489 }
449 } 490 }
450 491
451 distribution_c.clear(); 492 distribution_c.clear();
452 493
453 //!!! handle mean_c, median_c, variance_c 494 if (totalDuration > 0.0) {
495
496 double sum_c = 0.0;
497
498 for (int k = 0; k < sz; ++k) {
499 double value = values[k] * toSec(durations[k]);
500 sum_c += value;
501 }
502
503 summary.mean_c = sum_c / totalDuration;
504
505 for (int k = 0; k < sz; ++k) {
506 double value = values[k] * toSec(durations[k]);
507 summary.variance_c +=
508 (value - summary.mean_c) * (value - summary.mean_c);
509 }
510
511 summary.variance_c /= summary.count;
512 }
513
514 //!!! still to handle: median_c
454 515
455 float mean = summary.sum / summary.count; 516 float mean = summary.sum / summary.count;
456 517
457 for (int k = 0; k < sz; ++k) { 518 for (int k = 0; k < sz; ++k) {
458 summary.variance += (values[k] - mean) * (values[k] - mean); 519 summary.variance += (values[k] - mean) * (values[k] - mean);