annotate src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 354:e85513153c71

Initialise rate to 0. Otherwise there's a danger plugins will change the SampleType (e.g. to VariableSampleRate) but not set the rate because they don't think they need it (when in fact it needs to be set to 0)
author Chris Cannam
date Thu, 28 Mar 2013 15:49:17 +0000
parents d5c5a52e6c9f
children 92b1fbb1cc87
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@337 72 #else
Chris@337 73 #include "../vamp-sdk/FFTimpl.cpp"
cannam@233 74 #endif
cannam@233 75
cannam@233 76
cannam@263 77 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
cannam@263 78
cannam@233 79 namespace Vamp {
cannam@233 80
cannam@233 81 namespace HostExt {
cannam@233 82
cannam@233 83 class PluginInputDomainAdapter::Impl
cannam@233 84 {
cannam@233 85 public:
cannam@233 86 Impl(Plugin *plugin, float inputSampleRate);
cannam@233 87 ~Impl();
cannam@233 88
cannam@233 89 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
cannam@288 90 void reset();
cannam@233 91
cannam@233 92 size_t getPreferredStepSize() const;
cannam@233 93 size_t getPreferredBlockSize() const;
cannam@233 94
cannam@233 95 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@288 96
cannam@288 97 void setProcessTimestampMethod(ProcessTimestampMethod m);
cannam@288 98 ProcessTimestampMethod getProcessTimestampMethod() const;
cannam@233 99
cannam@233 100 RealTime getTimestampAdjustment() const;
cannam@233 101
Chris@317 102 WindowType getWindowType() const;
Chris@317 103 void setWindowType(WindowType type);
Chris@317 104
cannam@233 105 protected:
cannam@233 106 Plugin *m_plugin;
cannam@233 107 float m_inputSampleRate;
cannam@233 108 int m_channels;
cannam@288 109 int m_stepSize;
cannam@233 110 int m_blockSize;
cannam@233 111 float **m_freqbuf;
cannam@233 112
cannam@233 113 double *m_ri;
Chris@317 114
Chris@317 115 WindowType m_windowType;
Chris@317 116 Window<double> *m_window;
cannam@233 117
cannam@288 118 ProcessTimestampMethod m_method;
cannam@288 119 int m_processCount;
cannam@289 120 float **m_shiftBuffers;
cannam@288 121
cannam@233 122 #ifdef HAVE_FFTW3
cannam@233 123 fftw_plan m_plan;
cannam@233 124 fftw_complex *m_cbuf;
cannam@233 125 #else
cannam@233 126 double *m_ro;
cannam@233 127 double *m_io;
cannam@233 128 #endif
cannam@233 129
cannam@289 130 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
cannam@289 131 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
cannam@289 132
cannam@233 133 size_t makeBlockSizeAcceptable(size_t) const;
Chris@317 134
Chris@317 135 Window<double>::WindowType convertType(WindowType t) const;
cannam@233 136 };
cannam@233 137
cannam@233 138 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
cannam@233 139 PluginWrapper(plugin)
cannam@233 140 {
cannam@233 141 m_impl = new Impl(plugin, m_inputSampleRate);
cannam@233 142 }
cannam@233 143
cannam@233 144 PluginInputDomainAdapter::~PluginInputDomainAdapter()
cannam@233 145 {
cannam@233 146 delete m_impl;
cannam@233 147 }
cannam@233 148
cannam@233 149 bool
cannam@233 150 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 151 {
cannam@233 152 return m_impl->initialise(channels, stepSize, blockSize);
cannam@233 153 }
cannam@233 154
cannam@288 155 void
cannam@288 156 PluginInputDomainAdapter::reset()
cannam@288 157 {
cannam@288 158 m_impl->reset();
cannam@288 159 }
cannam@288 160
cannam@233 161 Plugin::InputDomain
cannam@233 162 PluginInputDomainAdapter::getInputDomain() const
cannam@233 163 {
cannam@233 164 return TimeDomain;
cannam@233 165 }
cannam@233 166
cannam@233 167 size_t
cannam@233 168 PluginInputDomainAdapter::getPreferredStepSize() const
cannam@233 169 {
cannam@233 170 return m_impl->getPreferredStepSize();
cannam@233 171 }
cannam@233 172
cannam@233 173 size_t
cannam@233 174 PluginInputDomainAdapter::getPreferredBlockSize() const
cannam@233 175 {
cannam@233 176 return m_impl->getPreferredBlockSize();
cannam@233 177 }
cannam@233 178
cannam@233 179 Plugin::FeatureSet
cannam@233 180 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@233 181 {
cannam@233 182 return m_impl->process(inputBuffers, timestamp);
cannam@233 183 }
cannam@233 184
cannam@288 185 void
cannam@288 186 PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 187 {
cannam@288 188 m_impl->setProcessTimestampMethod(m);
cannam@288 189 }
cannam@288 190
cannam@288 191 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 192 PluginInputDomainAdapter::getProcessTimestampMethod() const
cannam@288 193 {
cannam@288 194 return m_impl->getProcessTimestampMethod();
cannam@288 195 }
cannam@288 196
cannam@233 197 RealTime
cannam@233 198 PluginInputDomainAdapter::getTimestampAdjustment() const
cannam@233 199 {
cannam@233 200 return m_impl->getTimestampAdjustment();
cannam@233 201 }
cannam@233 202
Chris@317 203 PluginInputDomainAdapter::WindowType
Chris@317 204 PluginInputDomainAdapter::getWindowType() const
Chris@317 205 {
Chris@317 206 return m_impl->getWindowType();
Chris@317 207 }
Chris@317 208
Chris@317 209 void
Chris@317 210 PluginInputDomainAdapter::setWindowType(WindowType w)
Chris@317 211 {
Chris@317 212 m_impl->setWindowType(w);
Chris@317 213 }
Chris@317 214
cannam@233 215
cannam@233 216 PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@233 217 m_plugin(plugin),
cannam@233 218 m_inputSampleRate(inputSampleRate),
cannam@233 219 m_channels(0),
cannam@288 220 m_stepSize(0),
cannam@233 221 m_blockSize(0),
cannam@233 222 m_freqbuf(0),
cannam@233 223 m_ri(0),
Chris@317 224 m_windowType(HanningWindow),
cannam@233 225 m_window(0),
cannam@288 226 m_method(ShiftTimestamp),
cannam@288 227 m_processCount(0),
cannam@289 228 m_shiftBuffers(0),
cannam@233 229 #ifdef HAVE_FFTW3
cannam@233 230 m_plan(0),
cannam@233 231 m_cbuf(0)
cannam@233 232 #else
cannam@233 233 m_ro(0),
cannam@233 234 m_io(0)
cannam@233 235 #endif
cannam@233 236 {
cannam@233 237 }
cannam@233 238
cannam@233 239 PluginInputDomainAdapter::Impl::~Impl()
cannam@233 240 {
cannam@233 241 // the adapter will delete the plugin
cannam@233 242
cannam@289 243 if (m_shiftBuffers) {
cannam@289 244 for (int c = 0; c < m_channels; ++c) {
cannam@289 245 delete[] m_shiftBuffers[c];
cannam@289 246 }
cannam@289 247 delete[] m_shiftBuffers;
cannam@289 248 }
cannam@289 249
cannam@233 250 if (m_channels > 0) {
cannam@233 251 for (int c = 0; c < m_channels; ++c) {
cannam@233 252 delete[] m_freqbuf[c];
cannam@233 253 }
cannam@233 254 delete[] m_freqbuf;
cannam@233 255 #ifdef HAVE_FFTW3
cannam@233 256 if (m_plan) {
cannam@233 257 fftw_destroy_plan(m_plan);
cannam@233 258 fftw_free(m_ri);
cannam@233 259 fftw_free(m_cbuf);
cannam@233 260 m_plan = 0;
cannam@233 261 }
cannam@233 262 #else
cannam@233 263 delete[] m_ri;
cannam@233 264 delete[] m_ro;
cannam@233 265 delete[] m_io;
cannam@233 266 #endif
Chris@317 267
Chris@317 268 delete m_window;
cannam@233 269 }
cannam@233 270 }
cannam@233 271
cannam@233 272 // for some visual studii apparently
cannam@233 273 #ifndef M_PI
cannam@233 274 #define M_PI 3.14159265358979232846
cannam@233 275 #endif
cannam@233 276
cannam@233 277 bool
cannam@233 278 PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 279 {
cannam@233 280 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 281
cannam@288 282 m_stepSize = int(stepSize);
cannam@233 283 m_blockSize = int(blockSize);
cannam@233 284 m_channels = int(channels);
cannam@233 285
cannam@233 286 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 287 }
cannam@233 288
cannam@233 289 if (blockSize < 2) {
cannam@283 290 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
cannam@233 291 return false;
cannam@233 292 }
cannam@233 293
cannam@233 294 if (blockSize & (blockSize-1)) {
cannam@283 295 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
cannam@233 296 return false;
cannam@233 297 }
cannam@233 298
cannam@233 299 if (m_channels > 0) {
cannam@233 300 for (int c = 0; c < m_channels; ++c) {
cannam@233 301 delete[] m_freqbuf[c];
cannam@233 302 }
cannam@233 303 delete[] m_freqbuf;
cannam@233 304 #ifdef HAVE_FFTW3
cannam@233 305 if (m_plan) {
cannam@233 306 fftw_destroy_plan(m_plan);
cannam@233 307 fftw_free(m_ri);
cannam@233 308 fftw_free(m_cbuf);
cannam@233 309 m_plan = 0;
cannam@233 310 }
cannam@233 311 #else
cannam@233 312 delete[] m_ri;
cannam@233 313 delete[] m_ro;
cannam@233 314 delete[] m_io;
cannam@233 315 #endif
Chris@317 316 delete m_window;
cannam@233 317 }
cannam@233 318
cannam@288 319 m_stepSize = int(stepSize);
cannam@233 320 m_blockSize = int(blockSize);
cannam@233 321 m_channels = int(channels);
cannam@233 322
cannam@233 323 m_freqbuf = new float *[m_channels];
cannam@233 324 for (int c = 0; c < m_channels; ++c) {
cannam@233 325 m_freqbuf[c] = new float[m_blockSize + 2];
cannam@233 326 }
cannam@233 327
Chris@317 328 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
cannam@233 329
cannam@233 330 #ifdef HAVE_FFTW3
cannam@233 331 m_ri = (double *)fftw_malloc(blockSize * sizeof(double));
cannam@233 332 m_cbuf = (fftw_complex *)fftw_malloc((blockSize/2 + 1) * sizeof(fftw_complex));
cannam@233 333 m_plan = fftw_plan_dft_r2c_1d(blockSize, m_ri, m_cbuf, FFTW_MEASURE);
cannam@233 334 #else
cannam@233 335 m_ri = new double[m_blockSize];
cannam@233 336 m_ro = new double[m_blockSize];
cannam@233 337 m_io = new double[m_blockSize];
cannam@233 338 #endif
cannam@233 339
cannam@288 340 m_processCount = 0;
cannam@288 341
cannam@233 342 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 343 }
cannam@233 344
cannam@288 345 void
cannam@288 346 PluginInputDomainAdapter::Impl::reset()
cannam@288 347 {
cannam@288 348 m_processCount = 0;
cannam@288 349 m_plugin->reset();
cannam@288 350 }
cannam@288 351
cannam@233 352 size_t
cannam@233 353 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
cannam@233 354 {
cannam@233 355 size_t step = m_plugin->getPreferredStepSize();
cannam@233 356
cannam@233 357 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@233 358 step = getPreferredBlockSize() / 2;
cannam@233 359 }
cannam@233 360
cannam@233 361 return step;
cannam@233 362 }
cannam@233 363
cannam@233 364 size_t
cannam@233 365 PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
cannam@233 366 {
cannam@233 367 size_t block = m_plugin->getPreferredBlockSize();
cannam@233 368
cannam@233 369 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@233 370 if (block == 0) {
cannam@233 371 block = 1024;
cannam@233 372 } else {
cannam@233 373 block = makeBlockSizeAcceptable(block);
cannam@233 374 }
cannam@233 375 }
cannam@233 376
cannam@233 377 return block;
cannam@233 378 }
cannam@233 379
cannam@233 380 size_t
cannam@233 381 PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
cannam@233 382 {
cannam@233 383 if (blockSize < 2) {
cannam@233 384
cannam@283 385 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
cannam@233 386 << "supported, increasing from " << blockSize << " to 2" << std::endl;
cannam@233 387 blockSize = 2;
cannam@233 388
cannam@233 389 } else if (blockSize & (blockSize-1)) {
cannam@233 390
cannam@233 391 #ifdef HAVE_FFTW3
cannam@233 392 // not an issue with FFTW
cannam@233 393 #else
cannam@233 394
cannam@233 395 // not a power of two, can't handle that with our built-in FFT
cannam@233 396 // implementation
cannam@233 397
cannam@233 398 size_t nearest = blockSize;
cannam@233 399 size_t power = 0;
cannam@233 400 while (nearest > 1) {
cannam@233 401 nearest >>= 1;
cannam@233 402 ++power;
cannam@233 403 }
cannam@233 404 nearest = 1;
cannam@233 405 while (power) {
cannam@233 406 nearest <<= 1;
cannam@233 407 --power;
cannam@233 408 }
cannam@233 409
cannam@233 410 if (blockSize - nearest > (nearest*2) - blockSize) {
cannam@233 411 nearest = nearest*2;
cannam@233 412 }
cannam@233 413
cannam@283 414 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
cannam@233 415 blockSize = nearest;
cannam@233 416
cannam@233 417 #endif
cannam@233 418 }
cannam@233 419
cannam@233 420 return blockSize;
cannam@233 421 }
cannam@233 422
cannam@233 423 RealTime
cannam@233 424 PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
cannam@233 425 {
cannam@233 426 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 427 return RealTime::zeroTime;
cannam@298 428 } else if (m_method == ShiftData || m_method == NoShift) {
cannam@289 429 return RealTime::zeroTime;
cannam@233 430 } else {
cannam@233 431 return RealTime::frame2RealTime
cannam@233 432 (m_blockSize/2, int(m_inputSampleRate + 0.5));
cannam@233 433 }
cannam@233 434 }
cannam@233 435
cannam@288 436 void
cannam@288 437 PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 438 {
cannam@288 439 m_method = m;
cannam@288 440 }
cannam@288 441
cannam@288 442 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 443 PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
cannam@288 444 {
cannam@288 445 return m_method;
cannam@288 446 }
cannam@288 447
Chris@317 448 void
Chris@317 449 PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
Chris@317 450 {
Chris@317 451 if (m_windowType == t) return;
Chris@317 452 m_windowType = t;
Chris@317 453 if (m_window) {
Chris@317 454 delete m_window;
Chris@317 455 m_window = new Window<double>(convertType(m_windowType), m_blockSize);
Chris@317 456 }
Chris@317 457 }
Chris@317 458
Chris@317 459 PluginInputDomainAdapter::WindowType
Chris@317 460 PluginInputDomainAdapter::Impl::getWindowType() const
Chris@317 461 {
Chris@317 462 return m_windowType;
Chris@317 463 }
Chris@317 464
Chris@317 465 Window<double>::WindowType
Chris@317 466 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
Chris@317 467 {
Chris@317 468 switch (t) {
Chris@317 469 case RectangularWindow:
Chris@317 470 return Window<double>::RectangularWindow;
Chris@317 471 case BartlettWindow:
Chris@317 472 return Window<double>::BartlettWindow;
Chris@317 473 case HammingWindow:
Chris@317 474 return Window<double>::HammingWindow;
Chris@317 475 case HanningWindow:
Chris@317 476 return Window<double>::HanningWindow;
Chris@317 477 case BlackmanWindow:
Chris@317 478 return Window<double>::BlackmanWindow;
Chris@317 479 case NuttallWindow:
Chris@317 480 return Window<double>::NuttallWindow;
Chris@317 481 case BlackmanHarrisWindow:
Chris@317 482 return Window<double>::BlackmanHarrisWindow;
Chris@319 483 default:
Chris@319 484 return Window<double>::HanningWindow;
Chris@317 485 }
Chris@317 486 }
Chris@317 487
cannam@233 488 Plugin::FeatureSet
cannam@233 489 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
cannam@233 490 RealTime timestamp)
cannam@233 491 {
cannam@233 492 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 493 return m_plugin->process(inputBuffers, timestamp);
cannam@233 494 }
cannam@233 495
cannam@298 496 if (m_method == ShiftTimestamp || m_method == NoShift) {
cannam@289 497 return processShiftingTimestamp(inputBuffers, timestamp);
cannam@289 498 } else {
cannam@289 499 return processShiftingData(inputBuffers, timestamp);
cannam@289 500 }
cannam@289 501 }
cannam@233 502
cannam@289 503 Plugin::FeatureSet
cannam@289 504 PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
cannam@289 505 RealTime timestamp)
cannam@289 506 {
cannam@298 507 if (m_method == ShiftTimestamp) {
cannam@298 508 timestamp = timestamp + getTimestampAdjustment();
cannam@298 509 }
cannam@233 510
cannam@233 511 for (int c = 0; c < m_channels; ++c) {
cannam@233 512
Chris@317 513 m_window->cut(inputBuffers[c], m_ri);
cannam@233 514
cannam@233 515 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@233 516 // FFT shift
cannam@233 517 double value = m_ri[i];
cannam@233 518 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@233 519 m_ri[i + m_blockSize/2] = value;
cannam@233 520 }
cannam@233 521
cannam@233 522 #ifdef HAVE_FFTW3
cannam@233 523 fftw_execute(m_plan);
cannam@233 524
cannam@233 525 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 526 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@233 527 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@233 528 }
cannam@233 529 #else
cannam@233 530 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@233 531
cannam@233 532 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@233 533 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@233 534 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@233 535 }
cannam@233 536 #endif
cannam@233 537 }
cannam@233 538
cannam@289 539 return m_plugin->process(m_freqbuf, timestamp);
cannam@288 540 }
cannam@288 541
cannam@288 542 Plugin::FeatureSet
cannam@289 543 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
cannam@289 544 RealTime timestamp)
cannam@288 545 {
cannam@289 546 if (m_processCount == 0) {
cannam@289 547 if (!m_shiftBuffers) {
cannam@289 548 m_shiftBuffers = new float *[m_channels];
cannam@289 549 for (int c = 0; c < m_channels; ++c) {
cannam@289 550 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
cannam@289 551 }
cannam@289 552 }
cannam@289 553 for (int c = 0; c < m_channels; ++c) {
cannam@289 554 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 555 m_shiftBuffers[c][i] = 0.f;
cannam@289 556 }
cannam@289 557 }
cannam@289 558 }
cannam@289 559
cannam@289 560 for (int c = 0; c < m_channels; ++c) {
cannam@289 561 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 562 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
cannam@289 563 }
cannam@289 564 for (int i = 0; i < m_blockSize; ++i) {
cannam@289 565 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
cannam@289 566 }
cannam@289 567 }
cannam@289 568
cannam@289 569 for (int c = 0; c < m_channels; ++c) {
cannam@289 570
Chris@317 571 m_window->cut(m_shiftBuffers[c], m_ri);
cannam@289 572
cannam@289 573 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@289 574 // FFT shift
cannam@289 575 double value = m_ri[i];
cannam@289 576 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@289 577 m_ri[i + m_blockSize/2] = value;
cannam@289 578 }
cannam@289 579
cannam@289 580 #ifdef HAVE_FFTW3
cannam@289 581 fftw_execute(m_plan);
cannam@289 582
cannam@289 583 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 584 m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
cannam@289 585 m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
cannam@289 586 }
cannam@289 587 #else
cannam@289 588 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@289 589
cannam@289 590 for (int i = 0; i <= m_blockSize/2; ++i) {
cannam@289 591 m_freqbuf[c][i * 2] = float(m_ro[i]);
cannam@289 592 m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
cannam@289 593 }
cannam@289 594 #endif
cannam@289 595 }
cannam@289 596
cannam@289 597 ++m_processCount;
cannam@289 598
cannam@289 599 return m_plugin->process(m_freqbuf, timestamp);
cannam@233 600 }
cannam@233 601
cannam@233 602 #ifndef HAVE_FFTW3
cannam@233 603
cannam@233 604 #endif
cannam@233 605
cannam@233 606 }
cannam@233 607
cannam@233 608 }
cannam@233 609
cannam@263 610 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
cannam@263 611