annotate src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 415:1522e2f6d700

Fix handling of output sample rate in buffering adapter in case where SampleType is Fixed but no sample rate provided (which is invalid behaviour from the plugin, but we might as well do the right thing with it)
author Chris Cannam
date Fri, 04 Sep 2015 13:48:28 +0100
parents e0697515163f
children 35fa4733bc5d
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@356 72 #warning "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));
cannam@233 336 m_plan = fftw_plan_dft_r2c_1d(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 {
cannam@298 510 if (m_method == ShiftTimestamp) {
Chris@386 511 // we may need to add one nsec if timestamp +
Chris@386 512 // getTimestampAdjustment() rounds down
cannam@298 513 timestamp = timestamp + getTimestampAdjustment();
Chris@386 514 RealTime nsec(0, 1);
Chris@386 515 if (RealTime::realTime2Frame(timestamp, m_inputSampleRate) <
Chris@386 516 RealTime::realTime2Frame(timestamp + nsec, m_inputSampleRate)) {
Chris@386 517 timestamp = timestamp + nsec;
Chris@386 518 }
cannam@298 519 }
cannam@233 520
cannam@233 521 for (int c = 0; c < m_channels; ++c) {
cannam@233 522
Chris@317 523 m_window->cut(inputBuffers[c], m_ri);
cannam@233 524
cannam@233 525 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@233 526 // FFT shift
cannam@233 527 double value = m_ri[i];
cannam@233 528 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@233 529 m_ri[i + m_blockSize/2] = value;
cannam@233 530 }
cannam@233 531
cannam@233 532 #ifdef HAVE_FFTW3
cannam@233 533 fftw_execute(m_plan);
cannam@233 534
cannam@233 535 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 536 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@233 537 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@233 538 }
cannam@233 539 #else
cannam@233 540 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@233 541
cannam@233 542 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 543 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@233 544 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@233 545 }
cannam@233 546 #endif
cannam@233 547 }
cannam@233 548
cannam@289 549 return m_plugin->process(m_freqbuf, timestamp);
cannam@288 550 }
cannam@288 551
cannam@288 552 Plugin::FeatureSet
cannam@289 553 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
cannam@289 554 RealTime timestamp)
cannam@288 555 {
cannam@289 556 if (m_processCount == 0) {
cannam@289 557 if (!m_shiftBuffers) {
cannam@289 558 m_shiftBuffers = new float *[m_channels];
cannam@289 559 for (int c = 0; c < m_channels; ++c) {
cannam@289 560 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
cannam@289 561 }
cannam@289 562 }
cannam@289 563 for (int c = 0; c < m_channels; ++c) {
cannam@289 564 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 565 m_shiftBuffers[c][i] = 0.f;
cannam@289 566 }
cannam@289 567 }
cannam@289 568 }
cannam@289 569
cannam@289 570 for (int c = 0; c < m_channels; ++c) {
cannam@289 571 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 572 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
cannam@289 573 }
cannam@289 574 for (int i = 0; i < m_blockSize; ++i) {
cannam@289 575 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
cannam@289 576 }
cannam@289 577 }
cannam@289 578
cannam@289 579 for (int c = 0; c < m_channels; ++c) {
cannam@289 580
Chris@317 581 m_window->cut(m_shiftBuffers[c], m_ri);
cannam@289 582
cannam@289 583 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@289 584 // FFT shift
cannam@289 585 double value = m_ri[i];
cannam@289 586 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@289 587 m_ri[i + m_blockSize/2] = value;
cannam@289 588 }
cannam@289 589
cannam@289 590 #ifdef HAVE_FFTW3
cannam@289 591 fftw_execute(m_plan);
cannam@289 592
cannam@289 593 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 594 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@289 595 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@289 596 }
cannam@289 597 #else
cannam@289 598 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@289 599
cannam@289 600 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 601 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@289 602 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@289 603 }
cannam@289 604 #endif
cannam@289 605 }
cannam@289 606
cannam@289 607 ++m_processCount;
cannam@289 608
cannam@289 609 return m_plugin->process(m_freqbuf, timestamp);
cannam@233 610 }
cannam@233 611
cannam@233 612 #ifndef HAVE_FFTW3
cannam@233 613
cannam@233 614 #endif
cannam@233 615
cannam@233 616 }
cannam@233 617
cannam@233 618 }
cannam@233 619
cannam@263 620 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
cannam@263 621