annotate vamp-sdk/hostext/PluginSummarisingAdapter.cpp @ 174:a6346812db44

* PluginSummarisingAdapter now compiles -- though doesn't actually work yet
author cannam
date Tue, 05 Aug 2008 13:38:30 +0000
parents a6981e5dafe5
children 4811fb599a97
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@174 40
cannam@173 41 namespace Vamp {
cannam@173 42
cannam@173 43 namespace HostExt {
cannam@173 44
cannam@173 45 class PluginSummarisingAdapter::Impl
cannam@173 46 {
cannam@173 47 public:
cannam@173 48 Impl(Plugin *plugin, float inputSampleRate);
cannam@173 49 ~Impl();
cannam@173 50
cannam@173 51 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@173 52 FeatureSet getRemainingFeatures();
cannam@173 53
cannam@173 54 void setSummarySegmentBoundaries(const SegmentBoundaries &);
cannam@173 55
cannam@173 56 FeatureSet getSummary(SummaryType type);
cannam@173 57
cannam@173 58 protected:
cannam@174 59 Plugin *m_plugin;
cannam@174 60
cannam@173 61 SegmentBoundaries m_boundaries;
cannam@174 62
cannam@174 63 typedef std::vector<float> ValueList;
cannam@174 64 typedef std::map<int, ValueList> BinValueMap;
cannam@174 65
cannam@174 66 struct OutputAccumulator {
cannam@174 67 int count;
cannam@174 68 BinValueMap values;
cannam@174 69 };
cannam@174 70
cannam@174 71 typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
cannam@174 72 OutputAccumulatorMap m_accumulators;
cannam@174 73
cannam@174 74 struct OutputBinSummary {
cannam@174 75 float minimum;
cannam@174 76 float maximum;
cannam@174 77 float median;
cannam@174 78 float mode;
cannam@174 79 float sum;
cannam@174 80 float variance;
cannam@174 81 int count;
cannam@174 82 };
cannam@174 83
cannam@174 84 typedef std::map<int, OutputBinSummary> OutputSummary;
cannam@174 85 typedef std::map<RealTime, OutputSummary> SummarySegmentMap;
cannam@174 86 typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
cannam@174 87
cannam@174 88 OutputSummarySegmentMap m_summaries;
cannam@174 89
cannam@174 90 RealTime m_lastTimestamp;
cannam@174 91
cannam@174 92 void accumulate(const FeatureSet &fs, RealTime);
cannam@174 93 void accumulate(int output, const Feature &f, RealTime);
cannam@174 94 void reduce();
cannam@173 95 };
cannam@173 96
cannam@173 97 PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
cannam@173 98 PluginWrapper(plugin)
cannam@173 99 {
cannam@173 100 m_impl = new Impl(plugin, m_inputSampleRate);
cannam@173 101 }
cannam@173 102
cannam@173 103 PluginSummarisingAdapter::~PluginSummarisingAdapter()
cannam@173 104 {
cannam@173 105 delete m_impl;
cannam@173 106 }
cannam@173 107
cannam@173 108 Plugin::FeatureSet
cannam@173 109 PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@173 110 {
cannam@173 111 return m_impl->process(inputBuffers, timestamp);
cannam@173 112 }
cannam@173 113
cannam@174 114 Plugin::FeatureSet
cannam@174 115 PluginSummarisingAdapter::getRemainingFeatures()
cannam@174 116 {
cannam@174 117 return m_impl->getRemainingFeatures();
cannam@174 118 }
cannam@174 119
cannam@173 120
cannam@173 121 PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@174 122 m_plugin(plugin)
cannam@173 123 {
cannam@173 124 }
cannam@173 125
cannam@173 126 PluginSummarisingAdapter::Impl::~Impl()
cannam@173 127 {
cannam@173 128 }
cannam@173 129
cannam@174 130 Plugin::FeatureSet
cannam@174 131 PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp)
cannam@174 132 {
cannam@174 133 FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
cannam@174 134 accumulate(fs, timestamp);
cannam@174 135 m_lastTimestamp = timestamp;
cannam@174 136 return fs;
cannam@174 137 }
cannam@174 138
cannam@174 139 Plugin::FeatureSet
cannam@174 140 PluginSummarisingAdapter::Impl::getRemainingFeatures()
cannam@174 141 {
cannam@174 142 FeatureSet fs = m_plugin->getRemainingFeatures();
cannam@174 143 accumulate(fs, m_lastTimestamp);
cannam@174 144 reduce();
cannam@174 145 return fs;
cannam@174 146 }
cannam@174 147
cannam@174 148 void
cannam@174 149 PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
cannam@174 150 RealTime timestamp)
cannam@174 151 {
cannam@174 152 for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
cannam@174 153 for (FeatureList::const_iterator j = i->second.begin();
cannam@174 154 j != i->second.end(); ++j) {
cannam@174 155 accumulate(i->first, *j, timestamp);
cannam@174 156 }
cannam@174 157 }
cannam@174 158 }
cannam@174 159
cannam@174 160 void
cannam@174 161 PluginSummarisingAdapter::Impl::accumulate(int output,
cannam@174 162 const Feature &f,
cannam@174 163 RealTime timestamp)
cannam@174 164 {
cannam@174 165 //!!! use timestamp to determine which segment we're on
cannam@174 166 m_accumulators[output].count++;
cannam@174 167 for (int i = 0; i < int(f.values.size()); ++i) {
cannam@174 168 m_accumulators[output].values[i].push_back(f.values[i]);
cannam@174 169 }
cannam@174 170 }
cannam@174 171
cannam@174 172 void
cannam@174 173 PluginSummarisingAdapter::Impl::reduce()
cannam@174 174 {
cannam@174 175 RealTime segmentStart = RealTime::zeroTime; //!!!
cannam@174 176
cannam@174 177 for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
cannam@174 178 i != m_accumulators.end(); ++i) {
cannam@174 179
cannam@174 180 int output = i->first;
cannam@174 181 OutputAccumulator &accumulator = i->second;
cannam@174 182
cannam@174 183 for (BinValueMap::iterator j = accumulator.values.begin();
cannam@174 184 j != accumulator.values.end(); ++j) {
cannam@174 185
cannam@174 186 int bin = j->first;
cannam@174 187 ValueList &values = j->second;
cannam@174 188
cannam@174 189 OutputBinSummary summary;
cannam@174 190 summary.minimum = 0.f;
cannam@174 191 summary.maximum = 0.f;
cannam@174 192 summary.median = 0.f;
cannam@174 193 summary.mode = 0.f;
cannam@174 194 summary.sum = 0.f;
cannam@174 195 summary.variance = 0.f;
cannam@174 196 summary.count = accumulator.count;
cannam@174 197 if (summary.count == 0 || values.empty()) continue;
cannam@174 198
cannam@174 199 std::sort(values.begin(), values.end());
cannam@174 200 int sz = values.size();
cannam@174 201
cannam@174 202 summary.minimum = values[0];
cannam@174 203 summary.maximum = values[sz-1];
cannam@174 204
cannam@174 205 if (sz % 2 == 1) {
cannam@174 206 summary.median = values[sz/2];
cannam@174 207 } else {
cannam@174 208 summary.median = (values[sz/2] + values[sz/2 + 1]) / 2;
cannam@174 209 }
cannam@174 210
cannam@174 211 std::map<float, int> distribution;
cannam@174 212
cannam@174 213 for (int k = 0; k < sz; ++k) {
cannam@174 214 summary.sum += values[k];
cannam@174 215 ++distribution[values[k]];
cannam@174 216 }
cannam@174 217
cannam@174 218 int md = 0;
cannam@174 219
cannam@174 220 //!!! I don't like this. Really the mode should be the
cannam@174 221 //!!! value that spans the longest period of time, not the
cannam@174 222 //!!! one that appears in the largest number of distinct
cannam@174 223 //!!! features.
cannam@174 224
cannam@174 225 for (std::map<float, int>::iterator di = distribution.begin();
cannam@174 226 di != distribution.end(); ++di) {
cannam@174 227 if (di->second > md) {
cannam@174 228 md = di->second;
cannam@174 229 summary.mode = di->first;
cannam@174 230 }
cannam@174 231 }
cannam@174 232
cannam@174 233 distribution.clear();
cannam@174 234
cannam@174 235 float mean = summary.sum / summary.count;
cannam@174 236
cannam@174 237 for (int k = 0; k < sz; ++k) {
cannam@174 238 summary.variance += (values[k] - mean) * (values[k] - mean);
cannam@174 239 }
cannam@174 240 summary.variance /= summary.count;
cannam@174 241
cannam@174 242 m_summaries[output][segmentStart][bin] = summary;
cannam@174 243 }
cannam@174 244 }
cannam@174 245 }
cannam@174 246
cannam@174 247
cannam@174 248 }
cannam@174 249
cannam@174 250 }
cannam@174 251