annotate src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 373:2056dfdd42c6

Toward win64 build eventually
author Chris Cannam
date Wed, 06 Aug 2014 16:30:34 +0100
parents 92b1fbb1cc87
children 364e4653fe20
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
cannam@233 295 if (blockSize & (blockSize-1)) {
cannam@283 296 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
cannam@233 297 return false;
cannam@233 298 }
cannam@233 299
cannam@233 300 if (m_channels > 0) {
cannam@233 301 for (int c = 0; c < m_channels; ++c) {
cannam@233 302 delete[] m_freqbuf[c];
cannam@233 303 }
cannam@233 304 delete[] m_freqbuf;
cannam@233 305 #ifdef HAVE_FFTW3
cannam@233 306 if (m_plan) {
cannam@233 307 fftw_destroy_plan(m_plan);
cannam@233 308 fftw_free(m_ri);
cannam@233 309 fftw_free(m_cbuf);
cannam@233 310 m_plan = 0;
cannam@233 311 }
cannam@233 312 #else
cannam@233 313 delete[] m_ri;
cannam@233 314 delete[] m_ro;
cannam@233 315 delete[] m_io;
cannam@233 316 #endif
Chris@317 317 delete m_window;
cannam@233 318 }
cannam@233 319
cannam@288 320 m_stepSize = int(stepSize);
cannam@233 321 m_blockSize = int(blockSize);
cannam@233 322 m_channels = int(channels);
cannam@233 323
cannam@233 324 m_freqbuf = new float *[m_channels];
cannam@233 325 for (int c = 0; c < m_channels; ++c) {
cannam@233 326 m_freqbuf[c] = new float[m_blockSize + 2];
cannam@233 327 }
cannam@233 328
Chris@317 329 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
cannam@233 330
cannam@233 331 #ifdef HAVE_FFTW3
cannam@233 332 m_ri = (double *)fftw_malloc(blockSize * sizeof(double));
cannam@233 333 m_cbuf = (fftw_complex *)fftw_malloc((blockSize/2 + 1) * sizeof(fftw_complex));
cannam@233 334 m_plan = fftw_plan_dft_r2c_1d(blockSize, m_ri, m_cbuf, FFTW_MEASURE);
cannam@233 335 #else
cannam@233 336 m_ri = new double[m_blockSize];
cannam@233 337 m_ro = new double[m_blockSize];
cannam@233 338 m_io = new double[m_blockSize];
cannam@233 339 #endif
cannam@233 340
cannam@288 341 m_processCount = 0;
cannam@288 342
cannam@233 343 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 344 }
cannam@233 345
cannam@288 346 void
cannam@288 347 PluginInputDomainAdapter::Impl::reset()
cannam@288 348 {
cannam@288 349 m_processCount = 0;
cannam@288 350 m_plugin->reset();
cannam@288 351 }
cannam@288 352
cannam@233 353 size_t
cannam@233 354 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
cannam@233 355 {
cannam@233 356 size_t step = m_plugin->getPreferredStepSize();
cannam@233 357
cannam@233 358 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@233 359 step = getPreferredBlockSize() / 2;
cannam@233 360 }
cannam@233 361
cannam@233 362 return step;
cannam@233 363 }
cannam@233 364
cannam@233 365 size_t
cannam@233 366 PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
cannam@233 367 {
cannam@233 368 size_t block = m_plugin->getPreferredBlockSize();
cannam@233 369
cannam@233 370 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@233 371 if (block == 0) {
cannam@233 372 block = 1024;
cannam@233 373 } else {
cannam@233 374 block = makeBlockSizeAcceptable(block);
cannam@233 375 }
cannam@233 376 }
cannam@233 377
cannam@233 378 return block;
cannam@233 379 }
cannam@233 380
cannam@233 381 size_t
cannam@233 382 PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
cannam@233 383 {
cannam@233 384 if (blockSize < 2) {
cannam@233 385
cannam@283 386 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
cannam@233 387 << "supported, increasing from " << blockSize << " to 2" << std::endl;
cannam@233 388 blockSize = 2;
cannam@233 389
cannam@233 390 } else if (blockSize & (blockSize-1)) {
cannam@233 391
cannam@233 392 #ifdef HAVE_FFTW3
cannam@233 393 // not an issue with FFTW
cannam@233 394 #else
cannam@233 395
cannam@233 396 // not a power of two, can't handle that with our built-in FFT
cannam@233 397 // implementation
cannam@233 398
cannam@233 399 size_t nearest = blockSize;
cannam@233 400 size_t power = 0;
cannam@233 401 while (nearest > 1) {
cannam@233 402 nearest >>= 1;
cannam@233 403 ++power;
cannam@233 404 }
cannam@233 405 nearest = 1;
cannam@233 406 while (power) {
cannam@233 407 nearest <<= 1;
cannam@233 408 --power;
cannam@233 409 }
cannam@233 410
cannam@233 411 if (blockSize - nearest > (nearest*2) - blockSize) {
cannam@233 412 nearest = nearest*2;
cannam@233 413 }
cannam@233 414
cannam@283 415 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
cannam@233 416 blockSize = nearest;
cannam@233 417
cannam@233 418 #endif
cannam@233 419 }
cannam@233 420
cannam@233 421 return blockSize;
cannam@233 422 }
cannam@233 423
cannam@233 424 RealTime
cannam@233 425 PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
cannam@233 426 {
cannam@233 427 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 428 return RealTime::zeroTime;
cannam@298 429 } else if (m_method == ShiftData || m_method == NoShift) {
cannam@289 430 return RealTime::zeroTime;
cannam@233 431 } else {
cannam@233 432 return RealTime::frame2RealTime
cannam@233 433 (m_blockSize/2, int(m_inputSampleRate + 0.5));
cannam@233 434 }
cannam@233 435 }
cannam@233 436
cannam@288 437 void
cannam@288 438 PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 439 {
cannam@288 440 m_method = m;
cannam@288 441 }
cannam@288 442
cannam@288 443 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 444 PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
cannam@288 445 {
cannam@288 446 return m_method;
cannam@288 447 }
cannam@288 448
Chris@317 449 void
Chris@317 450 PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
Chris@317 451 {
Chris@317 452 if (m_windowType == t) return;
Chris@317 453 m_windowType = t;
Chris@317 454 if (m_window) {
Chris@317 455 delete m_window;
Chris@317 456 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
Chris@317 457 }
Chris@317 458 }
Chris@317 459
Chris@317 460 PluginInputDomainAdapter::WindowType
Chris@317 461 PluginInputDomainAdapter::Impl::getWindowType() const
Chris@317 462 {
Chris@317 463 return m_windowType;
Chris@317 464 }
Chris@317 465
Chris@317 466 Window<double>::WindowType
Chris@317 467 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
Chris@317 468 {
Chris@317 469 switch (t) {
Chris@317 470 case RectangularWindow:
Chris@317 471 return Window<double>::RectangularWindow;
Chris@317 472 case BartlettWindow:
Chris@317 473 return Window<double>::BartlettWindow;
Chris@317 474 case HammingWindow:
Chris@317 475 return Window<double>::HammingWindow;
Chris@317 476 case HanningWindow:
Chris@317 477 return Window<double>::HanningWindow;
Chris@317 478 case BlackmanWindow:
Chris@317 479 return Window<double>::BlackmanWindow;
Chris@317 480 case NuttallWindow:
Chris@317 481 return Window<double>::NuttallWindow;
Chris@317 482 case BlackmanHarrisWindow:
Chris@317 483 return Window<double>::BlackmanHarrisWindow;
Chris@319 484 default:
Chris@319 485 return Window<double>::HanningWindow;
Chris@317 486 }
Chris@317 487 }
Chris@317 488
cannam@233 489 Plugin::FeatureSet
cannam@233 490 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
cannam@233 491 RealTime timestamp)
cannam@233 492 {
cannam@233 493 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 494 return m_plugin->process(inputBuffers, timestamp);
cannam@233 495 }
cannam@233 496
cannam@298 497 if (m_method == ShiftTimestamp || m_method == NoShift) {
cannam@289 498 return processShiftingTimestamp(inputBuffers, timestamp);
cannam@289 499 } else {
cannam@289 500 return processShiftingData(inputBuffers, timestamp);
cannam@289 501 }
cannam@289 502 }
cannam@233 503
cannam@289 504 Plugin::FeatureSet
cannam@289 505 PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
cannam@289 506 RealTime timestamp)
cannam@289 507 {
cannam@298 508 if (m_method == ShiftTimestamp) {
cannam@298 509 timestamp = timestamp + getTimestampAdjustment();
cannam@298 510 }
cannam@233 511
cannam@233 512 for (int c = 0; c < m_channels; ++c) {
cannam@233 513
Chris@317 514 m_window->cut(inputBuffers[c], m_ri);
cannam@233 515
cannam@233 516 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@233 517 // FFT shift
cannam@233 518 double value = m_ri[i];
cannam@233 519 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@233 520 m_ri[i + m_blockSize/2] = value;
cannam@233 521 }
cannam@233 522
cannam@233 523 #ifdef HAVE_FFTW3
cannam@233 524 fftw_execute(m_plan);
cannam@233 525
cannam@233 526 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 527 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@233 528 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@233 529 }
cannam@233 530 #else
cannam@233 531 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@233 532
cannam@233 533 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 534 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@233 535 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@233 536 }
cannam@233 537 #endif
cannam@233 538 }
cannam@233 539
cannam@289 540 return m_plugin->process(m_freqbuf, timestamp);
cannam@288 541 }
cannam@288 542
cannam@288 543 Plugin::FeatureSet
cannam@289 544 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
cannam@289 545 RealTime timestamp)
cannam@288 546 {
cannam@289 547 if (m_processCount == 0) {
cannam@289 548 if (!m_shiftBuffers) {
cannam@289 549 m_shiftBuffers = new float *[m_channels];
cannam@289 550 for (int c = 0; c < m_channels; ++c) {
cannam@289 551 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
cannam@289 552 }
cannam@289 553 }
cannam@289 554 for (int c = 0; c < m_channels; ++c) {
cannam@289 555 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 556 m_shiftBuffers[c][i] = 0.f;
cannam@289 557 }
cannam@289 558 }
cannam@289 559 }
cannam@289 560
cannam@289 561 for (int c = 0; c < m_channels; ++c) {
cannam@289 562 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 563 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
cannam@289 564 }
cannam@289 565 for (int i = 0; i < m_blockSize; ++i) {
cannam@289 566 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
cannam@289 567 }
cannam@289 568 }
cannam@289 569
cannam@289 570 for (int c = 0; c < m_channels; ++c) {
cannam@289 571
Chris@317 572 m_window->cut(m_shiftBuffers[c], m_ri);
cannam@289 573
cannam@289 574 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@289 575 // FFT shift
cannam@289 576 double value = m_ri[i];
cannam@289 577 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@289 578 m_ri[i + m_blockSize/2] = value;
cannam@289 579 }
cannam@289 580
cannam@289 581 #ifdef HAVE_FFTW3
cannam@289 582 fftw_execute(m_plan);
cannam@289 583
cannam@289 584 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 585 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@289 586 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@289 587 }
cannam@289 588 #else
cannam@289 589 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@289 590
cannam@289 591 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 592 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@289 593 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@289 594 }
cannam@289 595 #endif
cannam@289 596 }
cannam@289 597
cannam@289 598 ++m_processCount;
cannam@289 599
cannam@289 600 return m_plugin->process(m_freqbuf, timestamp);
cannam@233 601 }
cannam@233 602
cannam@233 603 #ifndef HAVE_FFTW3
cannam@233 604
cannam@233 605 #endif
cannam@233 606
cannam@233 607 }
cannam@233 608
cannam@233 609 }
cannam@233 610
cannam@263 611 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
cannam@263 612