annotate VampTestPlugin.cpp @ 18:014cce47e998

Add an output that returns some actual feature of the input channels (also counting the channels, effectively)
author Chris Cannam
date Tue, 02 Dec 2014 18:02:36 +0000
parents ac7f544c7b20
children 534b001d8e8f
rev   line source
Chris@0 1
Chris@0 2
Chris@0 3 #include "VampTestPlugin.h"
Chris@0 4
Chris@3 5 #include <sstream>
Chris@18 6 #include <cmath>
Chris@3 7
Chris@3 8 using std::stringstream;
Chris@3 9
Chris@3 10 using Vamp::RealTime;
Chris@0 11
Chris@0 12 VampTestPlugin::VampTestPlugin(float inputSampleRate) :
Chris@3 13 Plugin(inputSampleRate),
Chris@17 14 m_produceOutput(true),
Chris@3 15 m_n(0),
Chris@18 16 m_channels(1),
Chris@3 17 m_stepSize(0),
Chris@3 18 m_blockSize(0)
Chris@0 19 {
Chris@3 20 for (int i = 0; i < 10; ++i) {
Chris@3 21 m_instants.push_back(RealTime::fromSeconds(1.5 * i));
Chris@3 22 }
Chris@0 23 }
Chris@0 24
Chris@0 25 VampTestPlugin::~VampTestPlugin()
Chris@0 26 {
Chris@0 27 }
Chris@0 28
Chris@0 29 string
Chris@0 30 VampTestPlugin::getIdentifier() const
Chris@0 31 {
Chris@0 32 return "vamp-test-plugin";
Chris@0 33 }
Chris@0 34
Chris@0 35 string
Chris@0 36 VampTestPlugin::getName() const
Chris@0 37 {
Chris@0 38 return "Vamp Test Plugin";
Chris@0 39 }
Chris@0 40
Chris@0 41 string
Chris@0 42 VampTestPlugin::getDescription() const
Chris@0 43 {
Chris@0 44 return "Test plugin for hosts handling various output types";
Chris@0 45 }
Chris@0 46
Chris@0 47 string
Chris@0 48 VampTestPlugin::getMaker() const
Chris@0 49 {
Chris@0 50 return "Chris Cannam";
Chris@0 51 }
Chris@0 52
Chris@0 53 int
Chris@0 54 VampTestPlugin::getPluginVersion() const
Chris@0 55 {
Chris@17 56 return 2;
Chris@0 57 }
Chris@0 58
Chris@0 59 string
Chris@0 60 VampTestPlugin::getCopyright() const
Chris@0 61 {
Chris@0 62 return "BSD";
Chris@0 63 }
Chris@0 64
Chris@0 65 VampTestPlugin::InputDomain
Chris@0 66 VampTestPlugin::getInputDomain() const
Chris@0 67 {
Chris@0 68 return TimeDomain;
Chris@0 69 }
Chris@0 70
Chris@0 71 size_t
Chris@0 72 VampTestPlugin::getPreferredBlockSize() const
Chris@0 73 {
Chris@0 74 return 0;
Chris@0 75 }
Chris@0 76
Chris@0 77 size_t
Chris@0 78 VampTestPlugin::getPreferredStepSize() const
Chris@0 79 {
Chris@0 80 return 0;
Chris@0 81 }
Chris@0 82
Chris@0 83 size_t
Chris@0 84 VampTestPlugin::getMinChannelCount() const
Chris@0 85 {
Chris@0 86 return 1;
Chris@0 87 }
Chris@0 88
Chris@0 89 size_t
Chris@0 90 VampTestPlugin::getMaxChannelCount() const
Chris@0 91 {
Chris@18 92 return 10;
Chris@0 93 }
Chris@0 94
Chris@0 95 VampTestPlugin::ParameterList
Chris@0 96 VampTestPlugin::getParameterDescriptors() const
Chris@0 97 {
Chris@0 98 ParameterList list;
Chris@17 99
Chris@17 100 // Provide one parameter, and make it so that we can easily tell
Chris@17 101 // whether it has been changed
Chris@17 102 ParameterDescriptor d;
Chris@17 103 d.identifier = "produce_output";
Chris@17 104 d.name = "Produce some output";
Chris@17 105 d.description = "Whether to produce any output. If this parameter is switched off, the plugin will produce no output. This is intended for basic testing of whether a host's parameter setting logic is functioning.";
Chris@17 106 d.unit = "";
Chris@17 107 d.minValue = 0;
Chris@17 108 d.maxValue = 1;
Chris@17 109 d.defaultValue = 1;
Chris@17 110 d.isQuantized = true;
Chris@17 111 d.quantizeStep = 1;
Chris@17 112 list.push_back(d);
Chris@17 113
Chris@0 114 return list;
Chris@0 115 }
Chris@0 116
Chris@0 117 float
Chris@0 118 VampTestPlugin::getParameter(string identifier) const
Chris@0 119 {
Chris@17 120 if (identifier == "produce_output") {
Chris@17 121 return m_produceOutput ? 1.f : 0.f;
Chris@17 122 }
Chris@0 123 return 0;
Chris@0 124 }
Chris@0 125
Chris@0 126 void
Chris@0 127 VampTestPlugin::setParameter(string identifier, float value)
Chris@0 128 {
Chris@17 129 if (identifier == "produce_output") {
Chris@17 130 m_produceOutput = (value > 0.5);
Chris@17 131 }
Chris@0 132 }
Chris@0 133
Chris@0 134 VampTestPlugin::ProgramList
Chris@0 135 VampTestPlugin::getPrograms() const
Chris@0 136 {
Chris@0 137 ProgramList list;
Chris@0 138 return list;
Chris@0 139 }
Chris@0 140
Chris@0 141 string
Chris@0 142 VampTestPlugin::getCurrentProgram() const
Chris@0 143 {
Chris@0 144 return ""; // no programs
Chris@0 145 }
Chris@0 146
Chris@0 147 void
Chris@0 148 VampTestPlugin::selectProgram(string name)
Chris@0 149 {
Chris@0 150 }
Chris@0 151
Chris@0 152 VampTestPlugin::OutputList
Chris@0 153 VampTestPlugin::getOutputDescriptors() const
Chris@0 154 {
Chris@0 155 OutputList list;
Chris@0 156
Chris@7 157 int n = 0;
Chris@7 158
Chris@0 159 OutputDescriptor d;
Chris@1 160
Chris@1 161 d.identifier = "instants";
Chris@1 162 d.name = "Instants";
Chris@2 163 d.description = "Single time points without values";
Chris@1 164 d.unit = "";
Chris@1 165 d.hasFixedBinCount = true;
Chris@1 166 d.binCount = 0;
Chris@1 167 d.hasKnownExtents = false;
Chris@1 168 d.isQuantized = false;
Chris@1 169 d.sampleType = OutputDescriptor::VariableSampleRate;
Chris@1 170 d.hasDuration = false;
Chris@7 171 m_outputNumbers[d.identifier] = n++;
Chris@1 172 list.push_back(d);
Chris@1 173
Chris@1 174 d.identifier = "curve-oss";
Chris@1 175 d.name = "Curve: OneSamplePerStep";
Chris@2 176 d.description = "A time series with one value per process block";
Chris@0 177 d.unit = "";
Chris@0 178 d.hasFixedBinCount = true;
Chris@0 179 d.binCount = 1;
Chris@0 180 d.hasKnownExtents = false;
Chris@0 181 d.isQuantized = false;
Chris@0 182 d.sampleType = OutputDescriptor::OneSamplePerStep;
Chris@0 183 d.hasDuration = false;
Chris@7 184 m_outputNumbers[d.identifier] = n++;
Chris@0 185 list.push_back(d);
Chris@0 186
Chris@1 187 d.identifier = "curve-fsr";
Chris@1 188 d.name = "Curve: FixedSampleRate";
Chris@2 189 d.description = "A time series with equally-spaced values (independent of process step size)";
Chris@1 190 d.unit = "";
Chris@1 191 d.hasFixedBinCount = true;
Chris@1 192 d.binCount = 1;
Chris@1 193 d.hasKnownExtents = false;
Chris@1 194 d.isQuantized = false;
Chris@1 195 d.sampleType = OutputDescriptor::FixedSampleRate;
Chris@8 196 d.sampleRate = 2.5;
Chris@1 197 d.hasDuration = false;
Chris@7 198 m_outputNumbers[d.identifier] = n++;
Chris@1 199 list.push_back(d);
Chris@1 200
Chris@7 201 d.identifier = "curve-fsr-timed";
Chris@7 202 d.name = "Curve: FixedSampleRate/Timed";
Chris@7 203 d.description = "A time series with a fixed sample rate (independent of process step size) but with timestamps on features";
Chris@7 204 d.unit = "";
Chris@7 205 d.hasFixedBinCount = true;
Chris@7 206 d.binCount = 1;
Chris@7 207 d.hasKnownExtents = false;
Chris@7 208 d.isQuantized = false;
Chris@7 209 d.sampleType = OutputDescriptor::FixedSampleRate;
Chris@8 210 d.sampleRate = 2.5;
Chris@7 211 d.hasDuration = false;
Chris@7 212 m_outputNumbers[d.identifier] = n++;
Chris@7 213 list.push_back(d);
Chris@7 214
Chris@1 215 d.identifier = "curve-vsr";
Chris@1 216 d.name = "Curve: VariableSampleRate";
Chris@2 217 d.description = "A variably-spaced series of values";
Chris@1 218 d.unit = "";
Chris@1 219 d.hasFixedBinCount = true;
Chris@1 220 d.binCount = 1;
Chris@1 221 d.hasKnownExtents = false;
Chris@1 222 d.isQuantized = false;
Chris@1 223 d.sampleType = OutputDescriptor::VariableSampleRate;
Chris@2 224 d.sampleRate = 0;
Chris@1 225 d.hasDuration = false;
Chris@7 226 m_outputNumbers[d.identifier] = n++;
Chris@1 227 list.push_back(d);
Chris@1 228
Chris@2 229 d.identifier = "grid-oss";
Chris@2 230 d.name = "Grid: OneSamplePerStep";
Chris@2 231 d.description = "A fixed-height grid of values with one column per process block";
Chris@2 232 d.unit = "";
Chris@2 233 d.hasFixedBinCount = true;
Chris@4 234 d.binCount = 10;
Chris@2 235 d.hasKnownExtents = false;
Chris@2 236 d.isQuantized = false;
Chris@4 237 d.sampleType = OutputDescriptor::OneSamplePerStep;
Chris@2 238 d.sampleRate = 0;
Chris@2 239 d.hasDuration = false;
Chris@7 240 m_outputNumbers[d.identifier] = n++;
Chris@2 241 list.push_back(d);
Chris@2 242
Chris@2 243 d.identifier = "grid-fsr";
Chris@2 244 d.name = "Grid: FixedSampleRate";
Chris@2 245 d.description = "A fixed-height grid of values with equally-spaced columns (independent of process step size)";
Chris@2 246 d.unit = "";
Chris@2 247 d.hasFixedBinCount = true;
Chris@4 248 d.binCount = 10;
Chris@2 249 d.hasKnownExtents = false;
Chris@2 250 d.isQuantized = false;
Chris@4 251 d.sampleType = OutputDescriptor::FixedSampleRate;
Chris@8 252 d.sampleRate = 2.5;
Chris@2 253 d.hasDuration = false;
Chris@7 254 m_outputNumbers[d.identifier] = n++;
Chris@2 255 list.push_back(d);
Chris@2 256
Chris@5 257 d.identifier = "notes-regions";
Chris@5 258 d.name = "Notes or Regions";
Chris@5 259 d.description = "Variably-spaced features with one value and duration";
Chris@5 260 d.unit = "";
Chris@5 261 d.hasFixedBinCount = true;
Chris@5 262 d.binCount = 1;
Chris@5 263 d.hasKnownExtents = false;
Chris@5 264 d.isQuantized = false;
Chris@5 265 d.sampleType = OutputDescriptor::VariableSampleRate;
Chris@5 266 d.sampleRate = 0;
Chris@5 267 d.hasDuration = true;
Chris@7 268 m_outputNumbers[d.identifier] = n++;
Chris@5 269 list.push_back(d);
Chris@2 270
Chris@18 271 d.identifier = "rmss";
Chris@18 272 d.name = "RMS of Input Channels";
Chris@18 273 d.description = "RMS levels of each input channel";
Chris@18 274 d.unit = "";
Chris@18 275 d.hasFixedBinCount = true;
Chris@18 276 d.binCount = m_channels;
Chris@18 277 d.hasKnownExtents = false;
Chris@18 278 d.isQuantized = false;
Chris@18 279 d.sampleType = OutputDescriptor::OneSamplePerStep;
Chris@18 280 d.hasDuration = false;
Chris@18 281 m_outputNumbers[d.identifier] = n++;
Chris@18 282 list.push_back(d);
Chris@18 283
Chris@0 284 return list;
Chris@0 285 }
Chris@0 286
Chris@0 287 bool
Chris@0 288 VampTestPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
Chris@0 289 {
Chris@0 290 if (channels < getMinChannelCount() ||
Chris@0 291 channels > getMaxChannelCount()) return false;
Chris@0 292
Chris@18 293 m_channels = channels;
Chris@3 294 m_stepSize = stepSize;
Chris@3 295 m_blockSize = blockSize;
Chris@0 296
Chris@0 297 return true;
Chris@0 298 }
Chris@0 299
Chris@0 300 void
Chris@0 301 VampTestPlugin::reset()
Chris@0 302 {
Chris@3 303 m_n = 0;
Chris@3 304 }
Chris@3 305
Chris@3 306 static Vamp::Plugin::Feature
Chris@3 307 instant(RealTime r, int i, int n)
Chris@3 308 {
Chris@3 309 std::stringstream s;
Chris@3 310 Vamp::Plugin::Feature f;
Chris@3 311 f.hasTimestamp = true;
Chris@3 312 f.timestamp = r;
Chris@3 313 f.hasDuration = false;
Chris@3 314 s << i+1 << " of " << n << " at " << r.toText();
Chris@3 315 f.label = s.str();
Chris@3 316 return f;
Chris@3 317 }
Chris@3 318
Chris@3 319 static Vamp::Plugin::Feature
Chris@3 320 untimedCurveValue(RealTime r, int i, int n)
Chris@3 321 {
Chris@3 322 std::stringstream s;
Chris@3 323 Vamp::Plugin::Feature f;
Chris@3 324 f.hasTimestamp = false;
Chris@3 325 f.hasDuration = false;
Chris@3 326 float v = float(i) / float(n);
Chris@3 327 f.values.push_back(v);
Chris@3 328 s << i+1 << " of " << n << ": " << v << " at " << r.toText();
Chris@3 329 f.label = s.str();
Chris@3 330 return f;
Chris@0 331 }
Chris@0 332
Chris@4 333 static Vamp::Plugin::Feature
Chris@4 334 timedCurveValue(RealTime r, int i, int n)
Chris@4 335 {
Chris@4 336 std::stringstream s;
Chris@4 337 Vamp::Plugin::Feature f;
Chris@4 338 f.hasTimestamp = true;
Chris@4 339 f.timestamp = r;
Chris@4 340 f.hasDuration = false;
Chris@4 341 float v = float(i) / float(n);
Chris@4 342 f.values.push_back(v);
Chris@4 343 s << i+1 << " of " << n << ": " << v << " at " << r.toText();
Chris@4 344 f.label = s.str();
Chris@4 345 return f;
Chris@4 346 }
Chris@4 347
Chris@4 348 static Vamp::Plugin::Feature
Chris@7 349 snappedCurveValue(RealTime r, RealTime sn, int i, int n)
Chris@7 350 {
Chris@7 351 std::stringstream s;
Chris@7 352 Vamp::Plugin::Feature f;
Chris@7 353 f.hasTimestamp = true;
Chris@7 354 f.timestamp = r;
Chris@7 355 f.hasDuration = false;
Chris@7 356 float v = float(i) / float(n);
Chris@7 357 f.values.push_back(v);
Chris@7 358 s << i+1 << " of " << n << ": " << v << " at " << r.toText() << " snap to " << sn.toText();
Chris@7 359 f.label = s.str();
Chris@7 360 return f;
Chris@7 361 }
Chris@7 362
Chris@7 363 static Vamp::Plugin::Feature
Chris@4 364 gridColumn(RealTime r, int i, int n)
Chris@4 365 {
Chris@4 366 std::stringstream s;
Chris@4 367 Vamp::Plugin::Feature f;
Chris@4 368 f.hasTimestamp = false;
Chris@4 369 f.hasDuration = false;
Chris@4 370 for (int j = 0; j < 10; ++j) {
Chris@4 371 float v = float(j + i + 2) / float(n + 10);
Chris@4 372 f.values.push_back(v);
Chris@4 373 }
Chris@4 374 s << i+1 << " of " << n << " at " << r.toText();
Chris@4 375 f.label = s.str();
Chris@4 376 return f;
Chris@4 377 }
Chris@4 378
Chris@5 379 static Vamp::Plugin::Feature
Chris@5 380 noteOrRegion(RealTime r, RealTime d, int i, int n)
Chris@5 381 {
Chris@5 382 std::stringstream s;
Chris@5 383 Vamp::Plugin::Feature f;
Chris@5 384 f.hasTimestamp = true;
Chris@5 385 f.timestamp = r;
Chris@5 386 f.hasDuration = true;
Chris@5 387 f.duration = d;
Chris@5 388 float v = float(i) / float(n);
Chris@5 389 f.values.push_back(v);
Chris@5 390 s << i+1 << " of " << n << ": " << v << " at " << r.toText() << " dur. " << d.toText();
Chris@5 391 f.label = s.str();
Chris@5 392 return f;
Chris@5 393 }
Chris@5 394
Chris@7 395 static
Chris@7 396 float snap(float x, float r)
Chris@7 397 {
Chris@7 398 int n = int(x / r + 0.5);
Chris@7 399 return n * r;
Chris@7 400 }
Chris@7 401
Chris@5 402 Vamp::Plugin::FeatureSet
Chris@5 403 VampTestPlugin::featuresFrom(RealTime timestamp, bool final)
Chris@0 404 {
Chris@3 405 FeatureSet fs;
Chris@3 406
Chris@3 407 RealTime endTime = timestamp + RealTime::frame2RealTime
Chris@3 408 (m_stepSize, m_inputSampleRate);
Chris@3 409
Chris@3 410 for (int i = 0; i < (int)m_instants.size(); ++i) {
Chris@5 411
Chris@5 412 if (m_instants[i] >= timestamp && (final || m_instants[i] < endTime)) {
Chris@7 413 fs[m_outputNumbers["instants"]]
Chris@7 414 .push_back(instant(m_instants[i], i, m_instants.size()));
Chris@3 415 }
Chris@4 416
Chris@4 417 RealTime variCurveTime = m_instants[i] / 2;
Chris@5 418 if (variCurveTime >= timestamp && (final || variCurveTime < endTime)) {
Chris@7 419 fs[m_outputNumbers["curve-vsr"]]
Chris@7 420 .push_back(timedCurveValue(variCurveTime, i, m_instants.size()));
Chris@4 421 }
Chris@5 422
Chris@5 423 RealTime noteTime = (m_instants[i] + m_instants[i]) / 3;
Chris@5 424 RealTime noteDuration = RealTime::fromSeconds((i % 2 == 0) ? 1.75 : 0.5);
Chris@5 425
Chris@5 426 if (noteTime >= timestamp && (final || noteTime < endTime)) {
Chris@7 427 fs[m_outputNumbers["notes-regions"]]
Chris@7 428 .push_back(noteOrRegion(noteTime, noteDuration, i, m_instants.size()));
Chris@5 429 }
Chris@3 430 }
Chris@3 431
Chris@5 432 if (!final) {
Chris@3 433
Chris@5 434 if (m_n < 20) {
Chris@7 435 fs[m_outputNumbers["curve-oss"]]
Chris@7 436 .push_back(untimedCurveValue(timestamp, m_n, 20));
Chris@5 437 }
Chris@3 438
Chris@5 439 if (m_n < 5) {
Chris@7 440 fs[m_outputNumbers["curve-fsr"]]
Chris@8 441 .push_back(untimedCurveValue(RealTime::fromSeconds(m_n / 2.5), m_n, 10));
Chris@6 442
Chris@7 443 float s = (m_n / 4) * 2;
Chris@7 444 if ((m_n % 4) > 0) {
Chris@7 445 s += float((m_n % 4) - 1) / 6.0;
Chris@7 446 }
Chris@7 447 fs[m_outputNumbers["curve-fsr-timed"]]
Chris@7 448 .push_back(snappedCurveValue(RealTime::fromSeconds(s),
Chris@8 449 RealTime::fromSeconds(snap(s, 0.4)),
Chris@7 450 m_n, 10));
Chris@5 451 }
Chris@5 452
Chris@5 453 if (m_n < 20) {
Chris@7 454 fs[m_outputNumbers["grid-oss"]]
Chris@7 455 .push_back(gridColumn(timestamp, m_n, 20));
Chris@5 456 }
Chris@5 457
Chris@5 458 } else {
Chris@5 459
Chris@5 460 for (int i = (m_n > 5 ? 5 : m_n); i < 10; ++i) {
Chris@7 461 fs[m_outputNumbers["curve-fsr"]]
Chris@8 462 .push_back(untimedCurveValue(RealTime::fromSeconds(i / 2.5), i, 10));
Chris@7 463
Chris@7 464 float s = (i / 4) * 2;
Chris@7 465 if ((i % 4) > 0) {
Chris@7 466 s += float((i % 4) - 1) / 6.0;
Chris@7 467 }
Chris@7 468 fs[m_outputNumbers["curve-fsr-timed"]]
Chris@7 469 .push_back(snappedCurveValue(RealTime::fromSeconds(s),
Chris@8 470 RealTime::fromSeconds(snap(s, 0.4)),
Chris@7 471 i, 10));
Chris@5 472 }
Chris@5 473
Chris@8 474 for (int i = 0; i < 10; ++i) {
Chris@7 475 fs[m_outputNumbers["grid-fsr"]]
Chris@9 476 .push_back(gridColumn(RealTime::fromSeconds(i / 2.5), i, 10));
Chris@5 477 }
Chris@4 478 }
Chris@4 479
Chris@3 480 m_lastTime = endTime;
Chris@3 481 m_n = m_n + 1;
Chris@3 482 return fs;
Chris@5 483 }
Chris@5 484
Chris@5 485 VampTestPlugin::FeatureSet
Chris@5 486 VampTestPlugin::process(const float *const *inputBuffers, RealTime timestamp)
Chris@5 487 {
Chris@17 488 if (!m_produceOutput) return FeatureSet();
Chris@5 489 FeatureSet fs = featuresFrom(timestamp, false);
Chris@18 490
Chris@18 491 Feature f;
Chris@18 492 for (int c = 0; c < m_channels; ++c) {
Chris@18 493 float sum = 0.f;
Chris@18 494 for (int i = 0; i < m_blockSize; ++i) {
Chris@18 495 sum += inputBuffers[c][i] * inputBuffers[c][i];
Chris@18 496 }
Chris@18 497 float rms = sqrtf(sum / m_blockSize);
Chris@18 498 f.values.push_back(rms);
Chris@18 499 }
Chris@18 500 fs[m_outputNumbers["rmss"]].push_back(f);
Chris@18 501
Chris@5 502 return fs;
Chris@0 503 }
Chris@0 504
Chris@0 505 VampTestPlugin::FeatureSet
Chris@0 506 VampTestPlugin::getRemainingFeatures()
Chris@0 507 {
Chris@17 508 if (!m_produceOutput) return FeatureSet();
Chris@5 509 FeatureSet fs = featuresFrom(m_lastTime, true);
Chris@3 510 return fs;
Chris@0 511 }
Chris@0 512