annotate src/rubberband-1.8.1/vamp/RubberBandVampPlugin.cpp @ 23:619f715526df sv_v2.1

Update Vamp plugin SDK to 2.5
author Chris Cannam
date Thu, 09 May 2013 10:52:46 +0100
parents 37bf6b4a2645
children
rev   line source
Chris@10 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@10 2
Chris@10 3 /*
Chris@10 4 Rubber Band Library
Chris@10 5 An audio time-stretching and pitch-shifting library.
Chris@10 6 Copyright 2007-2012 Particular Programs Ltd.
Chris@10 7
Chris@10 8 This program is free software; you can redistribute it and/or
Chris@10 9 modify it under the terms of the GNU General Public License as
Chris@10 10 published by the Free Software Foundation; either version 2 of the
Chris@10 11 License, or (at your option) any later version. See the file
Chris@10 12 COPYING included with this distribution for more information.
Chris@10 13
Chris@10 14 Alternatively, if you have a valid commercial licence for the
Chris@10 15 Rubber Band Library obtained by agreement with the copyright
Chris@10 16 holders, you may redistribute and/or modify it under the terms
Chris@10 17 described in that licence.
Chris@10 18
Chris@10 19 If you wish to distribute code using the Rubber Band Library
Chris@10 20 under terms other than those of the GNU General Public License,
Chris@10 21 you must obtain a valid commercial licence before doing so.
Chris@10 22 */
Chris@10 23
Chris@10 24 #include "RubberBandVampPlugin.h"
Chris@10 25
Chris@10 26 #include "StretchCalculator.h"
Chris@10 27 #include "system/sysutils.h"
Chris@10 28
Chris@10 29 #include <cmath>
Chris@10 30 #include <cstdio>
Chris@10 31
Chris@10 32 using std::string;
Chris@10 33 using std::vector;
Chris@10 34 using std::cerr;
Chris@10 35 using std::endl;
Chris@10 36
Chris@10 37 class RubberBandVampPlugin::Impl
Chris@10 38 {
Chris@10 39 public:
Chris@10 40 size_t m_stepSize;
Chris@10 41 size_t m_blockSize;
Chris@10 42 size_t m_sampleRate;
Chris@10 43
Chris@10 44 float m_timeRatio;
Chris@10 45 float m_pitchRatio;
Chris@10 46
Chris@10 47 bool m_realtime;
Chris@10 48 bool m_elasticTiming;
Chris@10 49 int m_transientMode;
Chris@10 50 bool m_phaseIndependent;
Chris@10 51 int m_windowLength;
Chris@10 52
Chris@10 53 RubberBand::RubberBandStretcher *m_stretcher;
Chris@10 54
Chris@10 55 int m_incrementsOutput;
Chris@10 56 int m_aggregateIncrementsOutput;
Chris@10 57 int m_divergenceOutput;
Chris@10 58 int m_phaseResetDfOutput;
Chris@10 59 int m_smoothedPhaseResetDfOutput;
Chris@10 60 int m_phaseResetPointsOutput;
Chris@10 61 int m_timeSyncPointsOutput;
Chris@10 62
Chris@10 63 size_t m_counter;
Chris@10 64 size_t m_accumulatedIncrement;
Chris@10 65
Chris@10 66 float **m_outputDump;
Chris@10 67
Chris@10 68 FeatureSet processOffline(const float *const *inputBuffers,
Chris@10 69 Vamp::RealTime timestamp);
Chris@10 70
Chris@10 71 FeatureSet getRemainingFeaturesOffline();
Chris@10 72
Chris@10 73 FeatureSet processRealTime(const float *const *inputBuffers,
Chris@10 74 Vamp::RealTime timestamp);
Chris@10 75
Chris@10 76 FeatureSet getRemainingFeaturesRealTime();
Chris@10 77
Chris@10 78 FeatureSet createFeatures(size_t inputIncrement,
Chris@10 79 std::vector<int> &outputIncrements,
Chris@10 80 std::vector<float> &phaseResetDf,
Chris@10 81 std::vector<int> &exactPoints,
Chris@10 82 std::vector<float> &smoothedDf,
Chris@10 83 size_t baseCount,
Chris@10 84 bool includeFinal);
Chris@10 85 };
Chris@10 86
Chris@10 87
Chris@10 88 RubberBandVampPlugin::RubberBandVampPlugin(float inputSampleRate) :
Chris@10 89 Plugin(inputSampleRate)
Chris@10 90 {
Chris@10 91 m_d = new Impl();
Chris@10 92 m_d->m_stepSize = 0;
Chris@10 93 m_d->m_timeRatio = 1.f;
Chris@10 94 m_d->m_pitchRatio = 1.f;
Chris@10 95 m_d->m_realtime = false;
Chris@10 96 m_d->m_elasticTiming = true;
Chris@10 97 m_d->m_transientMode = 0;
Chris@10 98 m_d->m_phaseIndependent = false;
Chris@10 99 m_d->m_windowLength = 0;
Chris@10 100 m_d->m_stretcher = 0;
Chris@10 101 m_d->m_sampleRate = lrintf(m_inputSampleRate);
Chris@10 102 }
Chris@10 103
Chris@10 104 RubberBandVampPlugin::~RubberBandVampPlugin()
Chris@10 105 {
Chris@10 106 if (m_d->m_outputDump) {
Chris@10 107 for (size_t i = 0; i < m_d->m_stretcher->getChannelCount(); ++i) {
Chris@10 108 delete[] m_d->m_outputDump[i];
Chris@10 109 }
Chris@10 110 delete[] m_d->m_outputDump;
Chris@10 111 }
Chris@10 112 delete m_d->m_stretcher;
Chris@10 113 delete m_d;
Chris@10 114 }
Chris@10 115
Chris@10 116 string
Chris@10 117 RubberBandVampPlugin::getIdentifier() const
Chris@10 118 {
Chris@10 119 return "rubberband";
Chris@10 120 }
Chris@10 121
Chris@10 122 string
Chris@10 123 RubberBandVampPlugin::getName() const
Chris@10 124 {
Chris@10 125 return "Rubber Band Timestretch Analysis";
Chris@10 126 }
Chris@10 127
Chris@10 128 string
Chris@10 129 RubberBandVampPlugin::getDescription() const
Chris@10 130 {
Chris@10 131 return "Carry out analysis phases of time stretcher process";
Chris@10 132 }
Chris@10 133
Chris@10 134 string
Chris@10 135 RubberBandVampPlugin::getMaker() const
Chris@10 136 {
Chris@10 137 return "Breakfast Quay";
Chris@10 138 }
Chris@10 139
Chris@10 140 int
Chris@10 141 RubberBandVampPlugin::getPluginVersion() const
Chris@10 142 {
Chris@10 143 return 1;
Chris@10 144 }
Chris@10 145
Chris@10 146 string
Chris@10 147 RubberBandVampPlugin::getCopyright() const
Chris@10 148 {
Chris@10 149 return "";//!!!
Chris@10 150 }
Chris@10 151
Chris@10 152 RubberBandVampPlugin::OutputList
Chris@10 153 RubberBandVampPlugin::getOutputDescriptors() const
Chris@10 154 {
Chris@10 155 OutputList list;
Chris@10 156
Chris@10 157 size_t rate = 0;
Chris@10 158 if (m_d->m_stretcher) {
Chris@10 159 rate = lrintf(m_inputSampleRate / m_d->m_stretcher->getInputIncrement());
Chris@10 160 }
Chris@10 161
Chris@10 162 OutputDescriptor d;
Chris@10 163 d.identifier = "increments";
Chris@10 164 d.name = "Output Increments";
Chris@10 165 d.description = "Output time increment for each input step";
Chris@10 166 d.unit = "samples";
Chris@10 167 d.hasFixedBinCount = true;
Chris@10 168 d.binCount = 1;
Chris@10 169 d.hasKnownExtents = false;
Chris@10 170 d.isQuantized = true;
Chris@10 171 d.quantizeStep = 1.0;
Chris@10 172 d.sampleType = OutputDescriptor::VariableSampleRate;
Chris@10 173 d.sampleRate = float(rate);
Chris@10 174 m_d->m_incrementsOutput = list.size();
Chris@10 175 list.push_back(d);
Chris@10 176
Chris@10 177 d.identifier = "aggregate_increments";
Chris@10 178 d.name = "Accumulated Output Increments";
Chris@10 179 d.description = "Accumulated output time increments";
Chris@10 180 d.sampleRate = 0;
Chris@10 181 m_d->m_aggregateIncrementsOutput = list.size();
Chris@10 182 list.push_back(d);
Chris@10 183
Chris@10 184 d.identifier = "divergence";
Chris@10 185 d.name = "Divergence from Linear";
Chris@10 186 d.description = "Difference between actual output time and the output time for a theoretical linear stretch";
Chris@10 187 d.isQuantized = false;
Chris@10 188 d.sampleRate = 0;
Chris@10 189 m_d->m_divergenceOutput = list.size();
Chris@10 190 list.push_back(d);
Chris@10 191
Chris@10 192 d.identifier = "phaseresetdf";
Chris@10 193 d.name = "Phase Reset Detection Function";
Chris@10 194 d.description = "Curve whose peaks are used to identify transients for phase reset points";
Chris@10 195 d.unit = "";
Chris@10 196 d.sampleRate = float(rate);
Chris@10 197 m_d->m_phaseResetDfOutput = list.size();
Chris@10 198 list.push_back(d);
Chris@10 199
Chris@10 200 d.identifier = "smoothedphaseresetdf";
Chris@10 201 d.name = "Smoothed Phase Reset Detection Function";
Chris@10 202 d.description = "Phase reset curve smoothed for peak picking";
Chris@10 203 d.unit = "";
Chris@10 204 m_d->m_smoothedPhaseResetDfOutput = list.size();
Chris@10 205 list.push_back(d);
Chris@10 206
Chris@10 207 d.identifier = "phaseresetpoints";
Chris@10 208 d.name = "Phase Reset Points";
Chris@10 209 d.description = "Points estimated as transients at which phase reset occurs";
Chris@10 210 d.unit = "";
Chris@10 211 d.hasFixedBinCount = true;
Chris@10 212 d.binCount = 0;
Chris@10 213 d.hasKnownExtents = false;
Chris@10 214 d.isQuantized = false;
Chris@10 215 d.sampleRate = 0;
Chris@10 216 m_d->m_phaseResetPointsOutput = list.size();
Chris@10 217 list.push_back(d);
Chris@10 218
Chris@10 219 d.identifier = "timesyncpoints";
Chris@10 220 d.name = "Time Sync Points";
Chris@10 221 d.description = "Salient points which stretcher aims to place with strictly correct timing";
Chris@10 222 d.unit = "";
Chris@10 223 d.hasFixedBinCount = true;
Chris@10 224 d.binCount = 0;
Chris@10 225 d.hasKnownExtents = false;
Chris@10 226 d.isQuantized = false;
Chris@10 227 d.sampleRate = 0;
Chris@10 228 m_d->m_timeSyncPointsOutput = list.size();
Chris@10 229 list.push_back(d);
Chris@10 230
Chris@10 231 return list;
Chris@10 232 }
Chris@10 233
Chris@10 234 RubberBandVampPlugin::ParameterList
Chris@10 235 RubberBandVampPlugin::getParameterDescriptors() const
Chris@10 236 {
Chris@10 237 ParameterList list;
Chris@10 238
Chris@10 239 ParameterDescriptor d;
Chris@10 240 d.identifier = "timeratio";
Chris@10 241 d.name = "Time Ratio";
Chris@10 242 d.description = "Ratio to modify overall duration by";
Chris@10 243 d.unit = "%";
Chris@10 244 d.minValue = 1;
Chris@10 245 d.maxValue = 500;
Chris@10 246 d.defaultValue = 100;
Chris@10 247 d.isQuantized = false;
Chris@10 248 list.push_back(d);
Chris@10 249
Chris@10 250 d.identifier = "pitchratio";
Chris@10 251 d.name = "Pitch Scale Ratio";
Chris@10 252 d.description = "Frequency ratio to modify pitch by";
Chris@10 253 d.unit = "%";
Chris@10 254 d.minValue = 1;
Chris@10 255 d.maxValue = 500;
Chris@10 256 d.defaultValue = 100;
Chris@10 257 d.isQuantized = false;
Chris@10 258 list.push_back(d);
Chris@10 259
Chris@10 260 d.identifier = "mode";
Chris@10 261 d.name = "Processing Mode";
Chris@10 262 d.description = ""; //!!!
Chris@10 263 d.unit = "";
Chris@10 264 d.minValue = 0;
Chris@10 265 d.maxValue = 1;
Chris@10 266 d.defaultValue = 0;
Chris@10 267 d.isQuantized = true;
Chris@10 268 d.quantizeStep = 1;
Chris@10 269 d.valueNames.clear();
Chris@10 270 d.valueNames.push_back("Offline");
Chris@10 271 d.valueNames.push_back("Real Time");
Chris@10 272 list.push_back(d);
Chris@10 273
Chris@10 274 d.identifier = "stretchtype";
Chris@10 275 d.name = "Stretch Flexibility";
Chris@10 276 d.description = ""; //!!!
Chris@10 277 d.unit = "";
Chris@10 278 d.minValue = 0;
Chris@10 279 d.maxValue = 1;
Chris@10 280 d.defaultValue = 0;
Chris@10 281 d.isQuantized = true;
Chris@10 282 d.quantizeStep = 1;
Chris@10 283 d.valueNames.clear();
Chris@10 284 d.valueNames.push_back("Elastic");
Chris@10 285 d.valueNames.push_back("Precise");
Chris@10 286 list.push_back(d);
Chris@10 287
Chris@10 288 d.identifier = "transientmode";
Chris@10 289 d.name = "Transient Handling";
Chris@10 290 d.description = ""; //!!!
Chris@10 291 d.unit = "";
Chris@10 292 d.minValue = 0;
Chris@10 293 d.maxValue = 2;
Chris@10 294 d.defaultValue = 0;
Chris@10 295 d.isQuantized = true;
Chris@10 296 d.quantizeStep = 1;
Chris@10 297 d.valueNames.clear();
Chris@10 298 d.valueNames.push_back("Mixed");
Chris@10 299 d.valueNames.push_back("Smooth");
Chris@10 300 d.valueNames.push_back("Crisp");
Chris@10 301 list.push_back(d);
Chris@10 302
Chris@10 303 d.identifier = "phasemode";
Chris@10 304 d.name = "Phase Handling";
Chris@10 305 d.description = ""; //!!!
Chris@10 306 d.unit = "";
Chris@10 307 d.minValue = 0;
Chris@10 308 d.maxValue = 1;
Chris@10 309 d.defaultValue = 0;
Chris@10 310 d.isQuantized = true;
Chris@10 311 d.quantizeStep = 1;
Chris@10 312 d.valueNames.clear();
Chris@10 313 d.valueNames.push_back("Laminar");
Chris@10 314 d.valueNames.push_back("Independent");
Chris@10 315 list.push_back(d);
Chris@10 316
Chris@10 317 d.identifier = "windowmode";
Chris@10 318 d.name = "Window Length";
Chris@10 319 d.description = ""; //!!!
Chris@10 320 d.unit = "";
Chris@10 321 d.minValue = 0;
Chris@10 322 d.maxValue = 2;
Chris@10 323 d.defaultValue = 0;
Chris@10 324 d.isQuantized = true;
Chris@10 325 d.quantizeStep = 1;
Chris@10 326 d.valueNames.clear();
Chris@10 327 d.valueNames.push_back("Standard");
Chris@10 328 d.valueNames.push_back("Short");
Chris@10 329 d.valueNames.push_back("Long");
Chris@10 330 list.push_back(d);
Chris@10 331
Chris@10 332 return list;
Chris@10 333 }
Chris@10 334
Chris@10 335 float
Chris@10 336 RubberBandVampPlugin::getParameter(std::string id) const
Chris@10 337 {
Chris@10 338 if (id == "timeratio") return m_d->m_timeRatio * 100.f;
Chris@10 339 if (id == "pitchratio") return m_d->m_pitchRatio * 100.f;
Chris@10 340 if (id == "mode") return m_d->m_realtime ? 1.f : 0.f;
Chris@10 341 if (id == "stretchtype") return m_d->m_elasticTiming ? 0.f : 1.f;
Chris@10 342 if (id == "transientmode") return float(m_d->m_transientMode);
Chris@10 343 if (id == "phasemode") return m_d->m_phaseIndependent ? 1.f : 0.f;
Chris@10 344 if (id == "windowmode") return float(m_d->m_windowLength);
Chris@10 345 return 0.f;
Chris@10 346 }
Chris@10 347
Chris@10 348 void
Chris@10 349 RubberBandVampPlugin::setParameter(std::string id, float value)
Chris@10 350 {
Chris@10 351 if (id == "timeratio") {
Chris@10 352 m_d->m_timeRatio = value / 100;
Chris@10 353 } else if (id == "pitchratio") {
Chris@10 354 m_d->m_pitchRatio = value / 100;
Chris@10 355 } else {
Chris@10 356 bool set = (value > 0.5);
Chris@10 357 if (id == "mode") m_d->m_realtime = set;
Chris@10 358 else if (id == "stretchtype") m_d->m_elasticTiming = !set;
Chris@10 359 else if (id == "transientmode") m_d->m_transientMode = int(value + 0.5);
Chris@10 360 else if (id == "phasemode") m_d->m_phaseIndependent = set;
Chris@10 361 else if (id == "windowmode") m_d->m_windowLength = int(value + 0.5);
Chris@10 362 }
Chris@10 363 }
Chris@10 364
Chris@10 365 bool
Chris@10 366 RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
Chris@10 367 {
Chris@10 368 if (channels < getMinChannelCount() ||
Chris@10 369 channels > getMaxChannelCount()) return false;
Chris@10 370
Chris@10 371 m_d->m_stepSize = std::min(stepSize, blockSize);
Chris@10 372 m_d->m_blockSize = stepSize;
Chris@10 373
Chris@10 374 RubberBand::RubberBandStretcher::Options options = 0;
Chris@10 375
Chris@10 376 if (m_d->m_realtime)
Chris@10 377 options |= RubberBand::RubberBandStretcher::OptionProcessRealTime;
Chris@10 378 else options |= RubberBand::RubberBandStretcher::OptionProcessOffline;
Chris@10 379
Chris@10 380 if (m_d->m_elasticTiming)
Chris@10 381 options |= RubberBand::RubberBandStretcher::OptionStretchElastic;
Chris@10 382 else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise;
Chris@10 383
Chris@10 384 if (m_d->m_transientMode == 0)
Chris@10 385 options |= RubberBand::RubberBandStretcher::OptionTransientsMixed;
Chris@10 386 else if (m_d->m_transientMode == 1)
Chris@10 387 options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth;
Chris@10 388 else options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp;
Chris@10 389
Chris@10 390 if (m_d->m_phaseIndependent)
Chris@10 391 options |= RubberBand::RubberBandStretcher::OptionPhaseIndependent;
Chris@10 392 else options |= RubberBand::RubberBandStretcher::OptionPhaseLaminar;
Chris@10 393
Chris@10 394 if (m_d->m_windowLength == 0)
Chris@10 395 options |= RubberBand::RubberBandStretcher::OptionWindowStandard;
Chris@10 396 else if (m_d->m_windowLength == 1)
Chris@10 397 options |= RubberBand::RubberBandStretcher::OptionWindowShort;
Chris@10 398 else options |= RubberBand::RubberBandStretcher::OptionWindowLong;
Chris@10 399
Chris@10 400 delete m_d->m_stretcher;
Chris@10 401 m_d->m_stretcher = new RubberBand::RubberBandStretcher
Chris@10 402 (m_d->m_sampleRate, channels, options);
Chris@10 403 m_d->m_stretcher->setDebugLevel(1);
Chris@10 404 m_d->m_stretcher->setTimeRatio(m_d->m_timeRatio);
Chris@10 405 m_d->m_stretcher->setPitchScale(m_d->m_pitchRatio);
Chris@10 406
Chris@10 407 m_d->m_counter = 0;
Chris@10 408 m_d->m_accumulatedIncrement = 0;
Chris@10 409
Chris@10 410 m_d->m_outputDump = 0;
Chris@10 411
Chris@10 412 return true;
Chris@10 413 }
Chris@10 414
Chris@10 415 void
Chris@10 416 RubberBandVampPlugin::reset()
Chris@10 417 {
Chris@10 418 if (m_d->m_stretcher) m_d->m_stretcher->reset();
Chris@10 419 }
Chris@10 420
Chris@10 421 RubberBandVampPlugin::FeatureSet
Chris@10 422 RubberBandVampPlugin::process(const float *const *inputBuffers,
Chris@10 423 Vamp::RealTime timestamp)
Chris@10 424 {
Chris@10 425 if (m_d->m_realtime) {
Chris@10 426 return m_d->processRealTime(inputBuffers, timestamp);
Chris@10 427 } else {
Chris@10 428 return m_d->processOffline(inputBuffers, timestamp);
Chris@10 429 }
Chris@10 430 }
Chris@10 431
Chris@10 432 RubberBandVampPlugin::FeatureSet
Chris@10 433 RubberBandVampPlugin::getRemainingFeatures()
Chris@10 434 {
Chris@10 435 if (m_d->m_realtime) {
Chris@10 436 return m_d->getRemainingFeaturesRealTime();
Chris@10 437 } else {
Chris@10 438 return m_d->getRemainingFeaturesOffline();
Chris@10 439 }
Chris@10 440 }
Chris@10 441
Chris@10 442 RubberBandVampPlugin::FeatureSet
Chris@10 443 RubberBandVampPlugin::Impl::processOffline(const float *const *inputBuffers,
Chris@10 444 Vamp::RealTime timestamp)
Chris@10 445 {
Chris@10 446 if (!m_stretcher) {
Chris@10 447 cerr << "ERROR: RubberBandVampPlugin::processOffline: "
Chris@10 448 << "RubberBandVampPlugin has not been initialised"
Chris@10 449 << endl;
Chris@10 450 return FeatureSet();
Chris@10 451 }
Chris@10 452
Chris@10 453 m_stretcher->study(inputBuffers, m_blockSize, false);
Chris@10 454 return FeatureSet();
Chris@10 455 }
Chris@10 456
Chris@10 457 RubberBandVampPlugin::FeatureSet
Chris@10 458 RubberBandVampPlugin::Impl::getRemainingFeaturesOffline()
Chris@10 459 {
Chris@10 460 m_stretcher->study(0, 0, true);
Chris@10 461
Chris@10 462 m_stretcher->calculateStretch();
Chris@10 463
Chris@10 464 int rate = m_sampleRate;
Chris@10 465
Chris@10 466 RubberBand::StretchCalculator sc(rate, m_stretcher->getInputIncrement(), true);
Chris@10 467
Chris@10 468 size_t inputIncrement = m_stretcher->getInputIncrement();
Chris@10 469 std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
Chris@10 470 std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve();
Chris@10 471 std::vector<int> peaks = m_stretcher->getExactTimePoints();
Chris@10 472 std::vector<float> smoothedDf = sc.smoothDF(phaseResetDf);
Chris@10 473
Chris@10 474 FeatureSet features = createFeatures
Chris@10 475 (inputIncrement, outputIncrements, phaseResetDf, peaks, smoothedDf,
Chris@10 476 0, true);
Chris@10 477
Chris@10 478 return features;
Chris@10 479 }
Chris@10 480
Chris@10 481 RubberBandVampPlugin::FeatureSet
Chris@10 482 RubberBandVampPlugin::Impl::processRealTime(const float *const *inputBuffers,
Chris@10 483 Vamp::RealTime timestamp)
Chris@10 484 {
Chris@10 485 // This function is not in any way a real-time function (i.e. it
Chris@10 486 // has no requirement to be RT safe); it simply operates the
Chris@10 487 // stretcher in RT mode.
Chris@10 488
Chris@10 489 if (!m_stretcher) {
Chris@10 490 cerr << "ERROR: RubberBandVampPlugin::processRealTime: "
Chris@10 491 << "RubberBandVampPlugin has not been initialised"
Chris@10 492 << endl;
Chris@10 493 return FeatureSet();
Chris@10 494 }
Chris@10 495
Chris@10 496 m_stretcher->process(inputBuffers, m_blockSize, false);
Chris@10 497
Chris@10 498 size_t inputIncrement = m_stretcher->getInputIncrement();
Chris@10 499 std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
Chris@10 500 std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve();
Chris@10 501 std::vector<float> smoothedDf; // not meaningful in RT mode
Chris@10 502 std::vector<int> dummyPoints;
Chris@10 503 FeatureSet features = createFeatures
Chris@10 504 (inputIncrement, outputIncrements, phaseResetDf, dummyPoints, smoothedDf,
Chris@10 505 m_counter, false);
Chris@10 506 m_counter += outputIncrements.size();
Chris@10 507
Chris@10 508 int available = 0;
Chris@10 509 while ((available = m_stretcher->available()) > 0) {
Chris@10 510 if (!m_outputDump) {
Chris@10 511 m_outputDump = new float *[m_stretcher->getChannelCount()];
Chris@10 512 for (size_t i = 0; i < m_stretcher->getChannelCount(); ++i) {
Chris@10 513 m_outputDump[i] = new float[m_blockSize];
Chris@10 514 }
Chris@10 515 }
Chris@10 516 m_stretcher->retrieve(m_outputDump,
Chris@10 517 std::min(int(m_blockSize), available));
Chris@10 518 }
Chris@10 519
Chris@10 520 return features;
Chris@10 521 }
Chris@10 522
Chris@10 523 RubberBandVampPlugin::FeatureSet
Chris@10 524 RubberBandVampPlugin::Impl::getRemainingFeaturesRealTime()
Chris@10 525 {
Chris@10 526 return FeatureSet();
Chris@10 527 }
Chris@10 528
Chris@10 529 RubberBandVampPlugin::FeatureSet
Chris@10 530 RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement,
Chris@10 531 std::vector<int> &outputIncrements,
Chris@10 532 std::vector<float> &phaseResetDf,
Chris@10 533 std::vector<int> &exactPoints,
Chris@10 534 std::vector<float> &smoothedDf,
Chris@10 535 size_t baseCount,
Chris@10 536 bool includeFinal)
Chris@10 537 {
Chris@10 538 size_t actual = m_accumulatedIncrement;
Chris@10 539
Chris@10 540 double overallRatio = m_timeRatio * m_pitchRatio;
Chris@10 541
Chris@10 542 char label[200];
Chris@10 543
Chris@10 544 FeatureSet features;
Chris@10 545
Chris@10 546 int rate = m_sampleRate;
Chris@10 547
Chris@10 548 size_t epi = 0;
Chris@10 549
Chris@10 550 for (size_t i = 0; i < outputIncrements.size(); ++i) {
Chris@10 551
Chris@10 552 size_t frame = (baseCount + i) * inputIncrement;
Chris@10 553
Chris@10 554 int oi = outputIncrements[i];
Chris@10 555 bool hard = false;
Chris@10 556 bool soft = false;
Chris@10 557
Chris@10 558 if (oi < 0) {
Chris@10 559 oi = -oi;
Chris@10 560 hard = true;
Chris@10 561 }
Chris@10 562
Chris@10 563 if (epi < exactPoints.size() && int(i) == exactPoints[epi]) {
Chris@10 564 soft = true;
Chris@10 565 ++epi;
Chris@10 566 }
Chris@10 567
Chris@10 568 double linear = (frame * overallRatio);
Chris@10 569
Chris@10 570 Vamp::RealTime t = Vamp::RealTime::frame2RealTime(frame, rate);
Chris@10 571
Chris@10 572 Feature feature;
Chris@10 573 feature.hasTimestamp = true;
Chris@10 574 feature.timestamp = t;
Chris@10 575 feature.values.push_back(float(oi));
Chris@10 576 feature.label = Vamp::RealTime::frame2RealTime(oi, rate).toText();
Chris@10 577 features[m_incrementsOutput].push_back(feature);
Chris@10 578
Chris@10 579 feature.values.clear();
Chris@10 580 feature.values.push_back(float(actual));
Chris@10 581 feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText();
Chris@10 582 features[m_aggregateIncrementsOutput].push_back(feature);
Chris@10 583
Chris@10 584 feature.values.clear();
Chris@10 585 feature.values.push_back(actual - linear);
Chris@10 586
Chris@10 587 sprintf(label, "expected %ld, actual %ld, difference %ld (%s ms)",
Chris@10 588 long(linear), long(actual), long(actual - linear),
Chris@10 589 // frame2RealTime expects an integer frame number,
Chris@10 590 // hence our multiplication factor
Chris@10 591 (Vamp::RealTime::frame2RealTime
Chris@10 592 (lrintf((actual - linear) * 1000), rate) / 1000)
Chris@10 593 .toText().c_str());
Chris@10 594 feature.label = label;
Chris@10 595
Chris@10 596 features[m_divergenceOutput].push_back(feature);
Chris@10 597 actual += oi;
Chris@10 598
Chris@10 599 char buf[30];
Chris@10 600
Chris@10 601 if (i < phaseResetDf.size()) {
Chris@10 602 feature.values.clear();
Chris@10 603 feature.values.push_back(phaseResetDf[i]);
Chris@10 604 sprintf(buf, "%d", int(baseCount + i));
Chris@10 605 feature.label = buf;
Chris@10 606 features[m_phaseResetDfOutput].push_back(feature);
Chris@10 607 }
Chris@10 608
Chris@10 609 if (i < smoothedDf.size()) {
Chris@10 610 feature.values.clear();
Chris@10 611 feature.values.push_back(smoothedDf[i]);
Chris@10 612 features[m_smoothedPhaseResetDfOutput].push_back(feature);
Chris@10 613 }
Chris@10 614
Chris@10 615 if (hard) {
Chris@10 616 feature.values.clear();
Chris@10 617 feature.label = "Phase Reset";
Chris@10 618 features[m_phaseResetPointsOutput].push_back(feature);
Chris@10 619 }
Chris@10 620
Chris@10 621 if (hard || soft) {
Chris@10 622 feature.values.clear();
Chris@10 623 feature.label = "Time Sync";
Chris@10 624 features[m_timeSyncPointsOutput].push_back(feature);
Chris@10 625 }
Chris@10 626 }
Chris@10 627
Chris@10 628 if (includeFinal) {
Chris@10 629 Vamp::RealTime t = Vamp::RealTime::frame2RealTime
Chris@10 630 (inputIncrement * (baseCount + outputIncrements.size()), rate);
Chris@10 631 Feature feature;
Chris@10 632 feature.hasTimestamp = true;
Chris@10 633 feature.timestamp = t;
Chris@10 634 feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText();
Chris@10 635 feature.values.clear();
Chris@10 636 feature.values.push_back(float(actual));
Chris@10 637 features[m_aggregateIncrementsOutput].push_back(feature);
Chris@10 638
Chris@10 639 float linear = ((baseCount + outputIncrements.size())
Chris@10 640 * inputIncrement * overallRatio);
Chris@10 641 feature.values.clear();
Chris@10 642 feature.values.push_back(actual - linear);
Chris@10 643 feature.label = // see earlier comment
Chris@10 644 (Vamp::RealTime::frame2RealTime //!!! update this as earlier label
Chris@10 645 (lrintf((actual - linear) * 1000), rate) / 1000)
Chris@10 646 .toText();
Chris@10 647 features[m_divergenceOutput].push_back(feature);
Chris@10 648 }
Chris@10 649
Chris@10 650 m_accumulatedIncrement = actual;
Chris@10 651
Chris@10 652 return features;
Chris@10 653 }
Chris@10 654