annotate src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 425:6b2567f365b0 vampipe

Docs
author Chris Cannam
date Thu, 12 May 2016 14:43:10 +0100
parents 9a2998401bbe
children e979a9c4ffb6
rev   line source
cannam@233 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@233 2
cannam@233 3 /*
cannam@233 4 Vamp
cannam@233 5
cannam@233 6 An API for audio analysis and feature extraction plugins.
cannam@233 7
cannam@233 8 Centre for Digital Music, Queen Mary, University of London.
cannam@290 9 Copyright 2006-2009 Chris Cannam and QMUL.
cannam@233 10
cannam@233 11 This file is based in part on Don Cross's public domain FFT
cannam@233 12 implementation.
cannam@233 13
cannam@233 14 Permission is hereby granted, free of charge, to any person
cannam@233 15 obtaining a copy of this software and associated documentation
cannam@233 16 files (the "Software"), to deal in the Software without
cannam@233 17 restriction, including without limitation the rights to use, copy,
cannam@233 18 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@233 19 of the Software, and to permit persons to whom the Software is
cannam@233 20 furnished to do so, subject to the following conditions:
cannam@233 21
cannam@233 22 The above copyright notice and this permission notice shall be
cannam@233 23 included in all copies or substantial portions of the Software.
cannam@233 24
cannam@233 25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@233 26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@233 27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@233 28 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@233 29 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@233 30 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@233 31 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@233 32
cannam@233 33 Except as contained in this notice, the names of the Centre for
cannam@233 34 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@233 35 shall not be used in advertising or otherwise to promote the sale,
cannam@233 36 use or other dealings in this Software without prior written
cannam@233 37 authorization.
cannam@233 38 */
cannam@233 39
cannam@233 40 #include <vamp-hostsdk/PluginInputDomainAdapter.h>
cannam@233 41
cannam@233 42 #include <cmath>
cannam@233 43
Chris@317 44 #include "Window.h"
Chris@317 45
cannam@233 46
cannam@233 47 /**
cannam@233 48 * If you want to compile using FFTW instead of the built-in FFT
cannam@233 49 * implementation for the PluginInputDomainAdapter, define HAVE_FFTW3
cannam@233 50 * in the Makefile.
cannam@233 51 *
cannam@233 52 * Be aware that FFTW is licensed under the GPL -- unlike this SDK,
cannam@233 53 * which is provided under a more liberal BSD license in order to
cannam@233 54 * permit use in closed source applications. The use of FFTW would
cannam@233 55 * mean that your code would need to be licensed under the GPL as
cannam@233 56 * well. Do not define this symbol unless you understand and accept
cannam@233 57 * the implications of this.
cannam@233 58 *
cannam@233 59 * Parties such as Linux distribution packagers who redistribute this
cannam@233 60 * SDK for use in other programs should _not_ define this symbol, as
cannam@233 61 * it would change the effective licensing terms under which the SDK
cannam@233 62 * was available to third party developers.
cannam@233 63 *
cannam@233 64 * The default is not to use FFTW, and to use the built-in FFT instead.
cannam@233 65 *
cannam@233 66 * Note: The FFTW code uses FFTW_MEASURE, and so will perform badly on
cannam@233 67 * its first invocation unless the host has saved and restored FFTW
cannam@233 68 * wisdom (see the FFTW documentation).
cannam@233 69 */
cannam@233 70 #ifdef HAVE_FFTW3
cannam@233 71 #include <fftw3.h>
Chris@422 72 #pragma message("*** NOTE: Compiling with FFTW3 support will result in a GPL binary")
Chris@337 73 #else
Chris@337 74 #include "../vamp-sdk/FFTimpl.cpp"
cannam@233 75 #endif
cannam@233 76
cannam@233 77
cannam@263 78 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
cannam@263 79
cannam@233 80 namespace Vamp {
cannam@233 81
cannam@233 82 namespace HostExt {
cannam@233 83
cannam@233 84 class PluginInputDomainAdapter::Impl
cannam@233 85 {
cannam@233 86 public:
cannam@233 87 Impl(Plugin *plugin, float inputSampleRate);
cannam@233 88 ~Impl();
cannam@233 89
cannam@233 90 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
cannam@288 91 void reset();
cannam@233 92
cannam@233 93 size_t getPreferredStepSize() const;
cannam@233 94 size_t getPreferredBlockSize() const;
cannam@233 95
cannam@233 96 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@288 97
cannam@288 98 void setProcessTimestampMethod(ProcessTimestampMethod m);
cannam@288 99 ProcessTimestampMethod getProcessTimestampMethod() const;
cannam@233 100
cannam@233 101 RealTime getTimestampAdjustment() const;
cannam@233 102
Chris@317 103 WindowType getWindowType() const;
Chris@317 104 void setWindowType(WindowType type);
Chris@317 105
cannam@233 106 protected:
cannam@233 107 Plugin *m_plugin;
cannam@233 108 float m_inputSampleRate;
cannam@233 109 int m_channels;
cannam@288 110 int m_stepSize;
cannam@233 111 int m_blockSize;
cannam@233 112 float **m_freqbuf;
cannam@233 113
cannam@233 114 double *m_ri;
Chris@317 115
Chris@317 116 WindowType m_windowType;
Chris@317 117 Window<double> *m_window;
cannam@233 118
cannam@288 119 ProcessTimestampMethod m_method;
cannam@288 120 int m_processCount;
cannam@289 121 float **m_shiftBuffers;
cannam@288 122
cannam@233 123 #ifdef HAVE_FFTW3
cannam@233 124 fftw_plan m_plan;
cannam@233 125 fftw_complex *m_cbuf;
cannam@233 126 #else
cannam@233 127 double *m_ro;
cannam@233 128 double *m_io;
cannam@233 129 #endif
cannam@233 130
cannam@289 131 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
cannam@289 132 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
cannam@289 133
cannam@233 134 size_t makeBlockSizeAcceptable(size_t) const;
Chris@317 135
Chris@317 136 Window<double>::WindowType convertType(WindowType t) const;
cannam@233 137 };
cannam@233 138
cannam@233 139 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
cannam@233 140 PluginWrapper(plugin)
cannam@233 141 {
cannam@233 142 m_impl = new Impl(plugin, m_inputSampleRate);
cannam@233 143 }
cannam@233 144
cannam@233 145 PluginInputDomainAdapter::~PluginInputDomainAdapter()
cannam@233 146 {
cannam@233 147 delete m_impl;
cannam@233 148 }
cannam@233 149
cannam@233 150 bool
cannam@233 151 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 152 {
cannam@233 153 return m_impl->initialise(channels, stepSize, blockSize);
cannam@233 154 }
cannam@233 155
cannam@288 156 void
cannam@288 157 PluginInputDomainAdapter::reset()
cannam@288 158 {
cannam@288 159 m_impl->reset();
cannam@288 160 }
cannam@288 161
cannam@233 162 Plugin::InputDomain
cannam@233 163 PluginInputDomainAdapter::getInputDomain() const
cannam@233 164 {
cannam@233 165 return TimeDomain;
cannam@233 166 }
cannam@233 167
cannam@233 168 size_t
cannam@233 169 PluginInputDomainAdapter::getPreferredStepSize() const
cannam@233 170 {
cannam@233 171 return m_impl->getPreferredStepSize();
cannam@233 172 }
cannam@233 173
cannam@233 174 size_t
cannam@233 175 PluginInputDomainAdapter::getPreferredBlockSize() const
cannam@233 176 {
cannam@233 177 return m_impl->getPreferredBlockSize();
cannam@233 178 }
cannam@233 179
cannam@233 180 Plugin::FeatureSet
cannam@233 181 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@233 182 {
cannam@233 183 return m_impl->process(inputBuffers, timestamp);
cannam@233 184 }
cannam@233 185
cannam@288 186 void
cannam@288 187 PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 188 {
cannam@288 189 m_impl->setProcessTimestampMethod(m);
cannam@288 190 }
cannam@288 191
cannam@288 192 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 193 PluginInputDomainAdapter::getProcessTimestampMethod() const
cannam@288 194 {
cannam@288 195 return m_impl->getProcessTimestampMethod();
cannam@288 196 }
cannam@288 197
cannam@233 198 RealTime
cannam@233 199 PluginInputDomainAdapter::getTimestampAdjustment() const
cannam@233 200 {
cannam@233 201 return m_impl->getTimestampAdjustment();
cannam@233 202 }
cannam@233 203
Chris@317 204 PluginInputDomainAdapter::WindowType
Chris@317 205 PluginInputDomainAdapter::getWindowType() const
Chris@317 206 {
Chris@317 207 return m_impl->getWindowType();
Chris@317 208 }
Chris@317 209
Chris@317 210 void
Chris@317 211 PluginInputDomainAdapter::setWindowType(WindowType w)
Chris@317 212 {
Chris@317 213 m_impl->setWindowType(w);
Chris@317 214 }
Chris@317 215
cannam@233 216
cannam@233 217 PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@233 218 m_plugin(plugin),
cannam@233 219 m_inputSampleRate(inputSampleRate),
cannam@233 220 m_channels(0),
cannam@288 221 m_stepSize(0),
cannam@233 222 m_blockSize(0),
cannam@233 223 m_freqbuf(0),
cannam@233 224 m_ri(0),
Chris@317 225 m_windowType(HanningWindow),
cannam@233 226 m_window(0),
cannam@288 227 m_method(ShiftTimestamp),
cannam@288 228 m_processCount(0),
cannam@289 229 m_shiftBuffers(0),
cannam@233 230 #ifdef HAVE_FFTW3
cannam@233 231 m_plan(0),
cannam@233 232 m_cbuf(0)
cannam@233 233 #else
cannam@233 234 m_ro(0),
cannam@233 235 m_io(0)
cannam@233 236 #endif
cannam@233 237 {
cannam@233 238 }
cannam@233 239
cannam@233 240 PluginInputDomainAdapter::Impl::~Impl()
cannam@233 241 {
cannam@233 242 // the adapter will delete the plugin
cannam@233 243
cannam@289 244 if (m_shiftBuffers) {
cannam@289 245 for (int c = 0; c < m_channels; ++c) {
cannam@289 246 delete[] m_shiftBuffers[c];
cannam@289 247 }
cannam@289 248 delete[] m_shiftBuffers;
cannam@289 249 }
cannam@289 250
cannam@233 251 if (m_channels > 0) {
cannam@233 252 for (int c = 0; c < m_channels; ++c) {
cannam@233 253 delete[] m_freqbuf[c];
cannam@233 254 }
cannam@233 255 delete[] m_freqbuf;
cannam@233 256 #ifdef HAVE_FFTW3
cannam@233 257 if (m_plan) {
cannam@233 258 fftw_destroy_plan(m_plan);
cannam@233 259 fftw_free(m_ri);
cannam@233 260 fftw_free(m_cbuf);
cannam@233 261 m_plan = 0;
cannam@233 262 }
cannam@233 263 #else
cannam@233 264 delete[] m_ri;
cannam@233 265 delete[] m_ro;
cannam@233 266 delete[] m_io;
cannam@233 267 #endif
Chris@317 268
Chris@317 269 delete m_window;
cannam@233 270 }
cannam@233 271 }
cannam@233 272
cannam@233 273 // for some visual studii apparently
cannam@233 274 #ifndef M_PI
cannam@233 275 #define M_PI 3.14159265358979232846
cannam@233 276 #endif
cannam@233 277
cannam@233 278 bool
cannam@233 279 PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 280 {
cannam@233 281 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 282
cannam@288 283 m_stepSize = int(stepSize);
cannam@233 284 m_blockSize = int(blockSize);
cannam@233 285 m_channels = int(channels);
cannam@233 286
cannam@233 287 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 288 }
cannam@233 289
cannam@233 290 if (blockSize < 2) {
cannam@283 291 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
cannam@233 292 return false;
cannam@233 293 }
cannam@233 294
Chris@384 295 #ifndef HAVE_FFTW3
cannam@233 296 if (blockSize & (blockSize-1)) {
cannam@283 297 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
cannam@233 298 return false;
cannam@233 299 }
Chris@384 300 #endif
cannam@233 301
cannam@233 302 if (m_channels > 0) {
cannam@233 303 for (int c = 0; c < m_channels; ++c) {
cannam@233 304 delete[] m_freqbuf[c];
cannam@233 305 }
cannam@233 306 delete[] m_freqbuf;
cannam@233 307 #ifdef HAVE_FFTW3
cannam@233 308 if (m_plan) {
cannam@233 309 fftw_destroy_plan(m_plan);
cannam@233 310 fftw_free(m_ri);
cannam@233 311 fftw_free(m_cbuf);
cannam@233 312 m_plan = 0;
cannam@233 313 }
cannam@233 314 #else
cannam@233 315 delete[] m_ri;
cannam@233 316 delete[] m_ro;
cannam@233 317 delete[] m_io;
cannam@233 318 #endif
Chris@317 319 delete m_window;
cannam@233 320 }
cannam@233 321
cannam@288 322 m_stepSize = int(stepSize);
cannam@233 323 m_blockSize = int(blockSize);
cannam@233 324 m_channels = int(channels);
cannam@233 325
cannam@233 326 m_freqbuf = new float *[m_channels];
cannam@233 327 for (int c = 0; c < m_channels; ++c) {
cannam@233 328 m_freqbuf[c] = new float[m_blockSize + 2];
cannam@233 329 }
cannam@233 330
Chris@317 331 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
cannam@233 332
cannam@233 333 #ifdef HAVE_FFTW3
cannam@233 334 m_ri = (double *)fftw_malloc(blockSize * sizeof(double));
cannam@233 335 m_cbuf = (fftw_complex *)fftw_malloc((blockSize/2 + 1) * sizeof(fftw_complex));
Chris@421 336 m_plan = fftw_plan_dft_r2c_1d(int(blockSize), m_ri, m_cbuf, FFTW_MEASURE);
cannam@233 337 #else
cannam@233 338 m_ri = new double[m_blockSize];
cannam@233 339 m_ro = new double[m_blockSize];
cannam@233 340 m_io = new double[m_blockSize];
cannam@233 341 #endif
cannam@233 342
cannam@288 343 m_processCount = 0;
cannam@288 344
cannam@233 345 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 346 }
cannam@233 347
cannam@288 348 void
cannam@288 349 PluginInputDomainAdapter::Impl::reset()
cannam@288 350 {
cannam@288 351 m_processCount = 0;
cannam@288 352 m_plugin->reset();
cannam@288 353 }
cannam@288 354
cannam@233 355 size_t
cannam@233 356 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
cannam@233 357 {
cannam@233 358 size_t step = m_plugin->getPreferredStepSize();
cannam@233 359
cannam@233 360 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@233 361 step = getPreferredBlockSize() / 2;
cannam@233 362 }
cannam@233 363
cannam@233 364 return step;
cannam@233 365 }
cannam@233 366
cannam@233 367 size_t
cannam@233 368 PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
cannam@233 369 {
cannam@233 370 size_t block = m_plugin->getPreferredBlockSize();
cannam@233 371
cannam@233 372 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@233 373 if (block == 0) {
cannam@233 374 block = 1024;
cannam@233 375 } else {
cannam@233 376 block = makeBlockSizeAcceptable(block);
cannam@233 377 }
cannam@233 378 }
cannam@233 379
cannam@233 380 return block;
cannam@233 381 }
cannam@233 382
cannam@233 383 size_t
cannam@233 384 PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
cannam@233 385 {
cannam@233 386 if (blockSize < 2) {
cannam@233 387
cannam@283 388 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
cannam@233 389 << "supported, increasing from " << blockSize << " to 2" << std::endl;
cannam@233 390 blockSize = 2;
cannam@233 391
cannam@233 392 } else if (blockSize & (blockSize-1)) {
cannam@233 393
cannam@233 394 #ifdef HAVE_FFTW3
cannam@233 395 // not an issue with FFTW
cannam@233 396 #else
cannam@233 397
cannam@233 398 // not a power of two, can't handle that with our built-in FFT
cannam@233 399 // implementation
cannam@233 400
cannam@233 401 size_t nearest = blockSize;
cannam@233 402 size_t power = 0;
cannam@233 403 while (nearest > 1) {
cannam@233 404 nearest >>= 1;
cannam@233 405 ++power;
cannam@233 406 }
cannam@233 407 nearest = 1;
cannam@233 408 while (power) {
cannam@233 409 nearest <<= 1;
cannam@233 410 --power;
cannam@233 411 }
cannam@233 412
cannam@233 413 if (blockSize - nearest > (nearest*2) - blockSize) {
cannam@233 414 nearest = nearest*2;
cannam@233 415 }
cannam@233 416
cannam@283 417 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
cannam@233 418 blockSize = nearest;
cannam@233 419
cannam@233 420 #endif
cannam@233 421 }
cannam@233 422
cannam@233 423 return blockSize;
cannam@233 424 }
cannam@233 425
cannam@233 426 RealTime
cannam@233 427 PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
cannam@233 428 {
cannam@233 429 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 430 return RealTime::zeroTime;
cannam@298 431 } else if (m_method == ShiftData || m_method == NoShift) {
cannam@289 432 return RealTime::zeroTime;
cannam@233 433 } else {
cannam@233 434 return RealTime::frame2RealTime
cannam@233 435 (m_blockSize/2, int(m_inputSampleRate + 0.5));
cannam@233 436 }
cannam@233 437 }
cannam@233 438
cannam@288 439 void
cannam@288 440 PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 441 {
cannam@288 442 m_method = m;
cannam@288 443 }
cannam@288 444
cannam@288 445 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 446 PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
cannam@288 447 {
cannam@288 448 return m_method;
cannam@288 449 }
cannam@288 450
Chris@317 451 void
Chris@317 452 PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
Chris@317 453 {
Chris@317 454 if (m_windowType == t) return;
Chris@317 455 m_windowType = t;
Chris@317 456 if (m_window) {
Chris@317 457 delete m_window;
Chris@317 458 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
Chris@317 459 }
Chris@317 460 }
Chris@317 461
Chris@317 462 PluginInputDomainAdapter::WindowType
Chris@317 463 PluginInputDomainAdapter::Impl::getWindowType() const
Chris@317 464 {
Chris@317 465 return m_windowType;
Chris@317 466 }
Chris@317 467
Chris@317 468 Window<double>::WindowType
Chris@317 469 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
Chris@317 470 {
Chris@317 471 switch (t) {
Chris@317 472 case RectangularWindow:
Chris@317 473 return Window<double>::RectangularWindow;
Chris@317 474 case BartlettWindow:
Chris@317 475 return Window<double>::BartlettWindow;
Chris@317 476 case HammingWindow:
Chris@317 477 return Window<double>::HammingWindow;
Chris@317 478 case HanningWindow:
Chris@317 479 return Window<double>::HanningWindow;
Chris@317 480 case BlackmanWindow:
Chris@317 481 return Window<double>::BlackmanWindow;
Chris@317 482 case NuttallWindow:
Chris@317 483 return Window<double>::NuttallWindow;
Chris@317 484 case BlackmanHarrisWindow:
Chris@317 485 return Window<double>::BlackmanHarrisWindow;
Chris@319 486 default:
Chris@319 487 return Window<double>::HanningWindow;
Chris@317 488 }
Chris@317 489 }
Chris@317 490
cannam@233 491 Plugin::FeatureSet
cannam@233 492 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
cannam@233 493 RealTime timestamp)
cannam@233 494 {
cannam@233 495 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 496 return m_plugin->process(inputBuffers, timestamp);
cannam@233 497 }
cannam@233 498
cannam@298 499 if (m_method == ShiftTimestamp || m_method == NoShift) {
cannam@289 500 return processShiftingTimestamp(inputBuffers, timestamp);
cannam@289 501 } else {
cannam@289 502 return processShiftingData(inputBuffers, timestamp);
cannam@289 503 }
cannam@289 504 }
cannam@233 505
cannam@289 506 Plugin::FeatureSet
cannam@289 507 PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
cannam@289 508 RealTime timestamp)
cannam@289 509 {
Chris@421 510 unsigned int roundedRate = 1;
Chris@421 511 if (m_inputSampleRate > 0.f) {
Chris@421 512 roundedRate = (unsigned int)round(m_inputSampleRate);
Chris@421 513 }
Chris@421 514
cannam@298 515 if (m_method == ShiftTimestamp) {
Chris@386 516 // we may need to add one nsec if timestamp +
Chris@386 517 // getTimestampAdjustment() rounds down
cannam@298 518 timestamp = timestamp + getTimestampAdjustment();
Chris@386 519 RealTime nsec(0, 1);
Chris@421 520 if (RealTime::realTime2Frame(timestamp, roundedRate) <
Chris@421 521 RealTime::realTime2Frame(timestamp + nsec, roundedRate)) {
Chris@386 522 timestamp = timestamp + nsec;
Chris@386 523 }
cannam@298 524 }
cannam@233 525
cannam@233 526 for (int c = 0; c < m_channels; ++c) {
cannam@233 527
Chris@317 528 m_window->cut(inputBuffers[c], m_ri);
cannam@233 529
cannam@233 530 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@233 531 // FFT shift
cannam@233 532 double value = m_ri[i];
cannam@233 533 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@233 534 m_ri[i + m_blockSize/2] = value;
cannam@233 535 }
cannam@233 536
cannam@233 537 #ifdef HAVE_FFTW3
cannam@233 538 fftw_execute(m_plan);
cannam@233 539
cannam@233 540 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 541 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@233 542 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@233 543 }
cannam@233 544 #else
cannam@233 545 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@233 546
cannam@233 547 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 548 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@233 549 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@233 550 }
cannam@233 551 #endif
cannam@233 552 }
cannam@233 553
cannam@289 554 return m_plugin->process(m_freqbuf, timestamp);
cannam@288 555 }
cannam@288 556
cannam@288 557 Plugin::FeatureSet
cannam@289 558 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
cannam@289 559 RealTime timestamp)
cannam@288 560 {
cannam@289 561 if (m_processCount == 0) {
cannam@289 562 if (!m_shiftBuffers) {
cannam@289 563 m_shiftBuffers = new float *[m_channels];
cannam@289 564 for (int c = 0; c < m_channels; ++c) {
cannam@289 565 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
cannam@289 566 }
cannam@289 567 }
cannam@289 568 for (int c = 0; c < m_channels; ++c) {
cannam@289 569 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 570 m_shiftBuffers[c][i] = 0.f;
cannam@289 571 }
cannam@289 572 }
cannam@289 573 }
cannam@289 574
cannam@289 575 for (int c = 0; c < m_channels; ++c) {
cannam@289 576 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 577 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
cannam@289 578 }
cannam@289 579 for (int i = 0; i < m_blockSize; ++i) {
cannam@289 580 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
cannam@289 581 }
cannam@289 582 }
cannam@289 583
cannam@289 584 for (int c = 0; c < m_channels; ++c) {
cannam@289 585
Chris@317 586 m_window->cut(m_shiftBuffers[c], m_ri);
cannam@289 587
cannam@289 588 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@289 589 // FFT shift
cannam@289 590 double value = m_ri[i];
cannam@289 591 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@289 592 m_ri[i + m_blockSize/2] = value;
cannam@289 593 }
cannam@289 594
cannam@289 595 #ifdef HAVE_FFTW3
cannam@289 596 fftw_execute(m_plan);
cannam@289 597
cannam@289 598 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 599 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@289 600 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@289 601 }
cannam@289 602 #else
cannam@289 603 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@289 604
cannam@289 605 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 606 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@289 607 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@289 608 }
cannam@289 609 #endif
cannam@289 610 }
cannam@289 611
cannam@289 612 ++m_processCount;
cannam@289 613
cannam@289 614 return m_plugin->process(m_freqbuf, timestamp);
cannam@233 615 }
cannam@233 616
cannam@233 617 #ifndef HAVE_FFTW3
cannam@233 618
cannam@233 619 #endif
cannam@233 620
cannam@233 621 }
cannam@233 622
cannam@233 623 }
cannam@233 624
cannam@263 625 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
cannam@263 626