Mercurial > hg > vamp-plugin-sdk
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); |