Mercurial > hg > vamp-test-plugin
comparison VampTestPlugin.cpp @ 31:c5c40824800a
Untabify, add copyright headers
author | Chris Cannam |
---|---|
date | Wed, 14 Sep 2016 17:13:01 +0100 |
parents | 867364fe9bf6 |
children | 4834aa2b49a6 |
comparison
equal
deleted
inserted
replaced
30:4bf93f93824d | 31:c5c40824800a |
---|---|
1 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ |
2 /* | |
3 Vamp Test Plugin | |
4 Copyright (c) 2013-2016 Queen Mary, University of London | |
5 | |
6 Permission is hereby granted, free of charge, to any person | |
7 obtaining a copy of this software and associated documentation | |
8 files (the "Software"), to deal in the Software without | |
9 restriction, including without limitation the rights to use, copy, | |
10 modify, merge, publish, distribute, sublicense, and/or sell copies | |
11 of the Software, and to permit persons to whom the Software is | |
12 furnished to do so, subject to the following conditions: | |
13 | |
14 The above copyright notice and this permission notice shall be | |
15 included in all copies or substantial portions of the Software. | |
16 | |
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
24 | |
25 Except as contained in this notice, the names of the Centre for | |
26 Digital Music and Queen Mary, University of London shall not be | |
27 used in advertising or otherwise to promote the sale, use or other | |
28 dealings in this Software without prior written authorization. | |
29 */ | |
2 | 30 |
3 #include "VampTestPlugin.h" | 31 #include "VampTestPlugin.h" |
4 | 32 |
5 #include <vamp-sdk/FFT.h> | 33 #include <vamp-sdk/FFT.h> |
6 | 34 |
20 m_channels(1), | 48 m_channels(1), |
21 m_stepSize(0), | 49 m_stepSize(0), |
22 m_blockSize(0) | 50 m_blockSize(0) |
23 { | 51 { |
24 for (int i = 0; i < 10; ++i) { | 52 for (int i = 0; i < 10; ++i) { |
25 m_instants.push_back(RealTime::fromSeconds(1.5 * i)); | 53 m_instants.push_back(RealTime::fromSeconds(1.5 * i)); |
26 } | 54 } |
27 } | 55 } |
28 | 56 |
29 VampTestPlugin::~VampTestPlugin() | 57 VampTestPlugin::~VampTestPlugin() |
30 { | 58 { |
32 | 60 |
33 string | 61 string |
34 VampTestPlugin::getIdentifier() const | 62 VampTestPlugin::getIdentifier() const |
35 { | 63 { |
36 if (m_frequencyDomain) { | 64 if (m_frequencyDomain) { |
37 return "vamp-test-plugin-freq"; | 65 return "vamp-test-plugin-freq"; |
38 } else { | 66 } else { |
39 return "vamp-test-plugin"; | 67 return "vamp-test-plugin"; |
40 } | 68 } |
41 } | 69 } |
42 | 70 |
43 string | 71 string |
44 VampTestPlugin::getName() const | 72 VampTestPlugin::getName() const |
45 { | 73 { |
46 if (m_frequencyDomain) { | 74 if (m_frequencyDomain) { |
47 return "Vamp Test Plugin (Frequency-Domain Input)"; | 75 return "Vamp Test Plugin (Frequency-Domain Input)"; |
48 } else { | 76 } else { |
49 return "Vamp Test Plugin"; | 77 return "Vamp Test Plugin"; |
50 } | 78 } |
51 } | 79 } |
52 | 80 |
53 string | 81 string |
54 VampTestPlugin::getDescription() const | 82 VampTestPlugin::getDescription() const |
128 | 156 |
129 float | 157 float |
130 VampTestPlugin::getParameter(string identifier) const | 158 VampTestPlugin::getParameter(string identifier) const |
131 { | 159 { |
132 if (identifier == "produce_output") { | 160 if (identifier == "produce_output") { |
133 return m_produceOutput ? 1.f : 0.f; | 161 return m_produceOutput ? 1.f : 0.f; |
134 } | 162 } |
135 return 0; | 163 return 0; |
136 } | 164 } |
137 | 165 |
138 void | 166 void |
139 VampTestPlugin::setParameter(string identifier, float value) | 167 VampTestPlugin::setParameter(string identifier, float value) |
140 { | 168 { |
141 if (identifier == "produce_output") { | 169 if (identifier == "produce_output") { |
142 m_produceOutput = (value > 0.5); | 170 m_produceOutput = (value > 0.5); |
143 } | 171 } |
144 } | 172 } |
145 | 173 |
146 VampTestPlugin::ProgramList | 174 VampTestPlugin::ProgramList |
147 VampTestPlugin::getPrograms() const | 175 VampTestPlugin::getPrograms() const |
311 | 339 |
312 bool | 340 bool |
313 VampTestPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) | 341 VampTestPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) |
314 { | 342 { |
315 if (channels < getMinChannelCount() || | 343 if (channels < getMinChannelCount() || |
316 channels > getMaxChannelCount()) return false; | 344 channels > getMaxChannelCount()) return false; |
317 | 345 |
318 m_channels = channels; | 346 m_channels = channels; |
319 m_stepSize = stepSize; | 347 m_stepSize = stepSize; |
320 m_blockSize = blockSize; | 348 m_blockSize = blockSize; |
321 | 349 |
391 stringstream s; | 419 stringstream s; |
392 Vamp::Plugin::Feature f; | 420 Vamp::Plugin::Feature f; |
393 f.hasTimestamp = false; | 421 f.hasTimestamp = false; |
394 f.hasDuration = false; | 422 f.hasDuration = false; |
395 for (int j = 0; j < 10; ++j) { | 423 for (int j = 0; j < 10; ++j) { |
396 float v = float(j + i + 2) / float(n + 10); | 424 float v = float(j + i + 2) / float(n + 10); |
397 f.values.push_back(v); | 425 f.values.push_back(v); |
398 } | 426 } |
399 s << i+1 << " of " << n << " at " << r.toText(); | 427 s << i+1 << " of " << n << " at " << r.toText(); |
400 f.label = s.str(); | 428 f.label = s.str(); |
401 return f; | 429 return f; |
402 } | 430 } |
428 VampTestPlugin::featuresFrom(RealTime timestamp, bool final) | 456 VampTestPlugin::featuresFrom(RealTime timestamp, bool final) |
429 { | 457 { |
430 FeatureSet fs; | 458 FeatureSet fs; |
431 | 459 |
432 RealTime endTime = timestamp + RealTime::frame2RealTime | 460 RealTime endTime = timestamp + RealTime::frame2RealTime |
433 (m_stepSize, m_inputSampleRate); | 461 (m_stepSize, m_inputSampleRate); |
434 | 462 |
435 for (int i = 0; i < (int)m_instants.size(); ++i) { | 463 for (int i = 0; i < (int)m_instants.size(); ++i) { |
436 | 464 |
437 if (m_instants[i] >= timestamp && (final || m_instants[i] < endTime)) { | 465 if (m_instants[i] >= timestamp && (final || m_instants[i] < endTime)) { |
438 fs[m_outputNumbers["instants"]] | 466 fs[m_outputNumbers["instants"]] |
439 .push_back(instant(m_instants[i], i, m_instants.size())); | 467 .push_back(instant(m_instants[i], i, m_instants.size())); |
440 } | 468 } |
441 | 469 |
442 RealTime variCurveTime = m_instants[i] / 2; | 470 RealTime variCurveTime = m_instants[i] / 2; |
443 if (variCurveTime >= timestamp && (final || variCurveTime < endTime)) { | 471 if (variCurveTime >= timestamp && (final || variCurveTime < endTime)) { |
444 fs[m_outputNumbers["curve-vsr"]] | 472 fs[m_outputNumbers["curve-vsr"]] |
445 .push_back(timedCurveValue(variCurveTime, i, m_instants.size())); | 473 .push_back(timedCurveValue(variCurveTime, i, m_instants.size())); |
446 } | 474 } |
447 | 475 |
448 RealTime noteTime = (m_instants[i] + m_instants[i]) / 3; | 476 RealTime noteTime = (m_instants[i] + m_instants[i]) / 3; |
449 RealTime noteDuration = RealTime::fromSeconds((i % 2 == 0) ? 1.75 : 0.5); | 477 RealTime noteDuration = RealTime::fromSeconds((i % 2 == 0) ? 1.75 : 0.5); |
450 | 478 |
451 if (noteTime >= timestamp && (final || noteTime < endTime)) { | 479 if (noteTime >= timestamp && (final || noteTime < endTime)) { |
452 fs[m_outputNumbers["notes-regions"]] | 480 fs[m_outputNumbers["notes-regions"]] |
453 .push_back(noteOrRegion(noteTime, noteDuration, i, m_instants.size())); | 481 .push_back(noteOrRegion(noteTime, noteDuration, i, m_instants.size())); |
454 } | 482 } |
455 } | 483 } |
456 | 484 |
457 if (!final) { | 485 if (!final) { |
458 | 486 |
459 if (m_n < 20) { | 487 if (m_n < 20) { |
460 fs[m_outputNumbers["curve-oss"]] | 488 fs[m_outputNumbers["curve-oss"]] |
461 .push_back(untimedCurveValue(timestamp, m_n, 20)); | 489 .push_back(untimedCurveValue(timestamp, m_n, 20)); |
462 } | 490 } |
463 | 491 |
464 if (m_n < 5) { | 492 if (m_n < 5) { |
465 fs[m_outputNumbers["curve-fsr"]] | 493 fs[m_outputNumbers["curve-fsr"]] |
466 .push_back(untimedCurveValue(RealTime::fromSeconds(m_n / 2.5), m_n, 10)); | 494 .push_back(untimedCurveValue(RealTime::fromSeconds(m_n / 2.5), m_n, 10)); |
467 | 495 |
468 float s = (m_n / 4) * 2; | 496 float s = (m_n / 4) * 2; |
469 if ((m_n % 4) > 0) { | 497 if ((m_n % 4) > 0) { |
470 s += float((m_n % 4) - 1) / 6.0; | 498 s += float((m_n % 4) - 1) / 6.0; |
471 } | 499 } |
472 fs[m_outputNumbers["curve-fsr-timed"]] | 500 fs[m_outputNumbers["curve-fsr-timed"]] |
473 .push_back(snappedCurveValue(RealTime::fromSeconds(s), | 501 .push_back(snappedCurveValue(RealTime::fromSeconds(s), |
474 RealTime::fromSeconds(snap(s, 0.4)), | 502 RealTime::fromSeconds(snap(s, 0.4)), |
475 m_n, 10)); | 503 m_n, 10)); |
476 } | 504 } |
477 | 505 |
478 if (m_n < 20) { | 506 if (m_n < 20) { |
479 fs[m_outputNumbers["grid-oss"]] | 507 fs[m_outputNumbers["grid-oss"]] |
480 .push_back(gridColumn(timestamp, m_n, 20)); | 508 .push_back(gridColumn(timestamp, m_n, 20)); |
481 } | 509 } |
482 | 510 |
483 } else { | 511 } else { |
484 | 512 |
485 for (int i = (m_n > 5 ? 5 : m_n); i < 10; ++i) { | 513 for (int i = (m_n > 5 ? 5 : m_n); i < 10; ++i) { |
486 fs[m_outputNumbers["curve-fsr"]] | 514 fs[m_outputNumbers["curve-fsr"]] |
487 .push_back(untimedCurveValue(RealTime::fromSeconds(i / 2.5), i, 10)); | 515 .push_back(untimedCurveValue(RealTime::fromSeconds(i / 2.5), i, 10)); |
488 | 516 |
489 float s = (i / 4) * 2; | 517 float s = (i / 4) * 2; |
490 if ((i % 4) > 0) { | 518 if ((i % 4) > 0) { |
491 s += float((i % 4) - 1) / 6.0; | 519 s += float((i % 4) - 1) / 6.0; |
492 } | 520 } |
493 fs[m_outputNumbers["curve-fsr-timed"]] | 521 fs[m_outputNumbers["curve-fsr-timed"]] |
494 .push_back(snappedCurveValue(RealTime::fromSeconds(s), | 522 .push_back(snappedCurveValue(RealTime::fromSeconds(s), |
495 RealTime::fromSeconds(snap(s, 0.4)), | 523 RealTime::fromSeconds(snap(s, 0.4)), |
496 i, 10)); | 524 i, 10)); |
497 } | 525 } |
498 | 526 |
499 for (int i = 0; i < 10; ++i) { | 527 for (int i = 0; i < 10; ++i) { |
500 fs[m_outputNumbers["grid-fsr"]] | 528 fs[m_outputNumbers["grid-fsr"]] |
501 .push_back(gridColumn(RealTime::fromSeconds(i / 2.5), i, 10)); | 529 .push_back(gridColumn(RealTime::fromSeconds(i / 2.5), i, 10)); |
502 } | 530 } |
503 } | 531 } |
504 | 532 |
505 m_lastTime = endTime; | 533 m_lastTime = endTime; |
506 m_n = m_n + 1; | 534 m_n = m_n + 1; |
507 return fs; | 535 return fs; |
515 | 543 |
516 Feature f; | 544 Feature f; |
517 float eps = 1e-6f; | 545 float eps = 1e-6f; |
518 | 546 |
519 for (int c = 0; c < m_channels; ++c) { | 547 for (int c = 0; c < m_channels; ++c) { |
520 if (!m_frequencyDomain) { | 548 if (!m_frequencyDomain) { |
521 // first value plus number of non-zero values | 549 // first value plus number of non-zero values |
522 float sum = inputBuffers[c][0]; | 550 float sum = inputBuffers[c][0]; |
523 for (int i = 0; i < m_blockSize; ++i) { | 551 for (int i = 0; i < m_blockSize; ++i) { |
524 if (fabsf(inputBuffers[c][i]) >= eps) sum += 1; | 552 if (fabsf(inputBuffers[c][i]) >= eps) sum += 1; |
525 } | 553 } |
526 f.values.push_back(sum); | 554 f.values.push_back(sum); |
527 } else { | 555 } else { |
528 // If we're in frequency-domain mode, we convert back to | 556 // If we're in frequency-domain mode, we convert back to |
529 // time-domain to calculate the input-summary feature | 557 // time-domain to calculate the input-summary feature |
530 // output. That should help the caller check that | 558 // output. That should help the caller check that |
531 // time-frequency conversion has gone more or less OK, | 559 // time-frequency conversion has gone more or less OK, |
532 // though they'll still have to bear in mind windowing and | 560 // though they'll still have to bear in mind windowing and |
533 // FFT shift (i.e. phase shift which puts the first | 561 // FFT shift (i.e. phase shift which puts the first |
534 // element in the middle of the frame) | 562 // element in the middle of the frame) |
535 vector<double> ri(m_blockSize, 0.0); | 563 vector<double> ri(m_blockSize, 0.0); |
536 vector<double> ii(m_blockSize, 0.0); | 564 vector<double> ii(m_blockSize, 0.0); |
537 vector<double> ro(m_blockSize, 0.0); | 565 vector<double> ro(m_blockSize, 0.0); |
538 vector<double> io(m_blockSize, 0.0); | 566 vector<double> io(m_blockSize, 0.0); |
539 for (int i = 0; i <= m_blockSize/2; ++i) { | 567 for (int i = 0; i <= m_blockSize/2; ++i) { |
540 ri[i] = inputBuffers[c][i*2]; | 568 ri[i] = inputBuffers[c][i*2]; |
541 ii[i] = inputBuffers[c][i*2 + 1]; | 569 ii[i] = inputBuffers[c][i*2 + 1]; |
542 if (i > 0) ri[m_blockSize-i] = ri[i]; | 570 if (i > 0) ri[m_blockSize-i] = ri[i]; |
543 if (i > 0) ii[m_blockSize-i] = -ii[i]; | 571 if (i > 0) ii[m_blockSize-i] = -ii[i]; |
544 } | 572 } |
545 Vamp::FFT::inverse(m_blockSize, &ri[0], &ii[0], &ro[0], &io[0]); | 573 Vamp::FFT::inverse(m_blockSize, &ri[0], &ii[0], &ro[0], &io[0]); |
546 float sum = 0; | 574 float sum = 0; |
547 for (int i = 0; i < m_blockSize; ++i) { | 575 for (int i = 0; i < m_blockSize; ++i) { |
548 if (fabs(ro[i]) >= eps) sum += 1; | 576 if (fabs(ro[i]) >= eps) sum += 1; |
549 } | 577 } |
550 sum += ro[0]; | 578 sum += ro[0]; |
551 f.values.push_back(sum); | 579 f.values.push_back(sum); |
552 } | 580 } |
553 } | 581 } |
554 | 582 |
555 fs[m_outputNumbers["input-summary"]].push_back(f); | 583 fs[m_outputNumbers["input-summary"]].push_back(f); |
556 | 584 |
557 f.values.clear(); | 585 f.values.clear(); |