annotate src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 444:7bab0c5422f4 vampipe

Make single/double-precision selectable for input domain adapter windowing and FFTs. Double precision is necessary to pass Sonic Annotator regression tests, though in practice most real-world methods would be fine with single precision.
author Chris Cannam
date Thu, 18 Aug 2016 14:43:52 +0100
parents 27c3448df198
children 7f7a10bcaff1
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
Chris@434 46 #include <stdlib.h>
Chris@434 47 #include <stdio.h>
Chris@434 48 #include <math.h>
Chris@434 49 #include <string.h>
Chris@434 50 #include <limits.h>
cannam@233 51
Chris@444 52 // Define this symbol in the build if you want to use single-precision
Chris@444 53 // FFTs in the input domain adapter. The default is to use
Chris@444 54 // double-precision FFTs.
Chris@444 55 //
Chris@444 56 //#define SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER 1
Chris@444 57
Chris@434 58 // Override C linkage for KissFFT headers. So long as we have already
Chris@434 59 // included all of the other (system etc) headers KissFFT depends on,
Chris@434 60 // this should work out OK
Chris@434 61 #undef __cplusplus
cannam@233 62
Chris@444 63 namespace Kiss {
Chris@444 64
Chris@434 65 #undef KISS_FFT_H
Chris@434 66 #undef KISS_FTR_H
Chris@434 67 #undef KISS_FFT__GUTS_H
Chris@434 68 #undef FIXED_POINT
Chris@434 69 #undef USE_SIMD
Chris@434 70 #undef kiss_fft_scalar
Chris@444 71
Chris@444 72 #ifdef SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER
Chris@444 73 typedef float kiss_fft_scalar;
Chris@434 74 #define kiss_fft_scalar float
Chris@444 75 #else
Chris@444 76 typedef double kiss_fft_scalar;
Chris@444 77 #define kiss_fft_scalar double
Chris@444 78 #endif
Chris@444 79
Chris@434 80 inline void free(void *ptr) { ::free(ptr); }
Chris@434 81 #include "../vamp-sdk/ext/kiss_fft.c"
Chris@434 82 #include "../vamp-sdk/ext/kiss_fftr.c"
Chris@444 83
Chris@444 84 #undef kiss_fft_scalar // leaving only the namespaced typedef
Chris@444 85
Chris@434 86 }
cannam@233 87
cannam@263 88 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
cannam@263 89
cannam@233 90 namespace Vamp {
cannam@233 91
cannam@233 92 namespace HostExt {
cannam@233 93
cannam@233 94 class PluginInputDomainAdapter::Impl
cannam@233 95 {
cannam@233 96 public:
cannam@233 97 Impl(Plugin *plugin, float inputSampleRate);
cannam@233 98 ~Impl();
cannam@233 99
cannam@233 100 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
cannam@288 101 void reset();
cannam@233 102
cannam@233 103 size_t getPreferredStepSize() const;
cannam@233 104 size_t getPreferredBlockSize() const;
cannam@233 105
cannam@233 106 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@288 107
cannam@288 108 void setProcessTimestampMethod(ProcessTimestampMethod m);
cannam@288 109 ProcessTimestampMethod getProcessTimestampMethod() const;
cannam@233 110
cannam@233 111 RealTime getTimestampAdjustment() const;
cannam@233 112
Chris@317 113 WindowType getWindowType() const;
Chris@317 114 void setWindowType(WindowType type);
Chris@317 115
cannam@233 116 protected:
cannam@233 117 Plugin *m_plugin;
cannam@233 118 float m_inputSampleRate;
cannam@233 119 int m_channels;
cannam@288 120 int m_stepSize;
cannam@233 121 int m_blockSize;
cannam@233 122 float **m_freqbuf;
Chris@444 123 Kiss::kiss_fft_scalar *m_ri;
Chris@317 124
Chris@317 125 WindowType m_windowType;
Chris@444 126 typedef Window<Kiss::kiss_fft_scalar> W;
Chris@444 127 W *m_window;
cannam@233 128
cannam@288 129 ProcessTimestampMethod m_method;
cannam@288 130 int m_processCount;
cannam@289 131 float **m_shiftBuffers;
cannam@288 132
Chris@444 133 Kiss::kiss_fftr_cfg m_cfg;
Chris@444 134 Kiss::kiss_fft_cpx *m_cbuf;
cannam@233 135
cannam@289 136 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
cannam@289 137 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
cannam@289 138
cannam@233 139 size_t makeBlockSizeAcceptable(size_t) const;
Chris@317 140
Chris@444 141 W::WindowType convertType(WindowType t) const;
cannam@233 142 };
cannam@233 143
cannam@233 144 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
cannam@233 145 PluginWrapper(plugin)
cannam@233 146 {
cannam@233 147 m_impl = new Impl(plugin, m_inputSampleRate);
cannam@233 148 }
cannam@233 149
cannam@233 150 PluginInputDomainAdapter::~PluginInputDomainAdapter()
cannam@233 151 {
cannam@233 152 delete m_impl;
cannam@233 153 }
cannam@233 154
cannam@233 155 bool
cannam@233 156 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 157 {
cannam@233 158 return m_impl->initialise(channels, stepSize, blockSize);
cannam@233 159 }
cannam@233 160
cannam@288 161 void
cannam@288 162 PluginInputDomainAdapter::reset()
cannam@288 163 {
cannam@288 164 m_impl->reset();
cannam@288 165 }
cannam@288 166
cannam@233 167 Plugin::InputDomain
cannam@233 168 PluginInputDomainAdapter::getInputDomain() const
cannam@233 169 {
cannam@233 170 return TimeDomain;
cannam@233 171 }
cannam@233 172
cannam@233 173 size_t
cannam@233 174 PluginInputDomainAdapter::getPreferredStepSize() const
cannam@233 175 {
cannam@233 176 return m_impl->getPreferredStepSize();
cannam@233 177 }
cannam@233 178
cannam@233 179 size_t
cannam@233 180 PluginInputDomainAdapter::getPreferredBlockSize() const
cannam@233 181 {
cannam@233 182 return m_impl->getPreferredBlockSize();
cannam@233 183 }
cannam@233 184
cannam@233 185 Plugin::FeatureSet
cannam@233 186 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@233 187 {
cannam@233 188 return m_impl->process(inputBuffers, timestamp);
cannam@233 189 }
cannam@233 190
cannam@288 191 void
cannam@288 192 PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 193 {
cannam@288 194 m_impl->setProcessTimestampMethod(m);
cannam@288 195 }
cannam@288 196
cannam@288 197 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 198 PluginInputDomainAdapter::getProcessTimestampMethod() const
cannam@288 199 {
cannam@288 200 return m_impl->getProcessTimestampMethod();
cannam@288 201 }
cannam@288 202
cannam@233 203 RealTime
cannam@233 204 PluginInputDomainAdapter::getTimestampAdjustment() const
cannam@233 205 {
cannam@233 206 return m_impl->getTimestampAdjustment();
cannam@233 207 }
cannam@233 208
Chris@317 209 PluginInputDomainAdapter::WindowType
Chris@317 210 PluginInputDomainAdapter::getWindowType() const
Chris@317 211 {
Chris@317 212 return m_impl->getWindowType();
Chris@317 213 }
Chris@317 214
Chris@317 215 void
Chris@317 216 PluginInputDomainAdapter::setWindowType(WindowType w)
Chris@317 217 {
Chris@317 218 m_impl->setWindowType(w);
Chris@317 219 }
Chris@317 220
cannam@233 221
cannam@233 222 PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@233 223 m_plugin(plugin),
cannam@233 224 m_inputSampleRate(inputSampleRate),
cannam@233 225 m_channels(0),
cannam@288 226 m_stepSize(0),
cannam@233 227 m_blockSize(0),
cannam@233 228 m_freqbuf(0),
cannam@233 229 m_ri(0),
Chris@317 230 m_windowType(HanningWindow),
cannam@233 231 m_window(0),
cannam@288 232 m_method(ShiftTimestamp),
cannam@288 233 m_processCount(0),
cannam@289 234 m_shiftBuffers(0),
Chris@434 235 m_cfg(0),
cannam@233 236 m_cbuf(0)
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;
Chris@435 256 delete[] m_ri;
Chris@434 257 if (m_cfg) {
Chris@444 258 Kiss::kiss_fftr_free(m_cfg);
Chris@435 259 m_cfg = 0;
Chris@434 260 delete[] m_cbuf;
Chris@435 261 m_cbuf = 0;
cannam@233 262 }
Chris@317 263 delete m_window;
cannam@233 264 }
cannam@233 265 }
cannam@233 266
cannam@233 267 // for some visual studii apparently
cannam@233 268 #ifndef M_PI
cannam@233 269 #define M_PI 3.14159265358979232846
cannam@233 270 #endif
cannam@233 271
cannam@233 272 bool
cannam@233 273 PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 274 {
cannam@233 275 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 276
cannam@288 277 m_stepSize = int(stepSize);
cannam@233 278 m_blockSize = int(blockSize);
cannam@233 279 m_channels = int(channels);
cannam@233 280
cannam@233 281 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@233 282 }
cannam@233 283
cannam@233 284 if (blockSize < 2) {
cannam@283 285 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
cannam@233 286 return false;
cannam@233 287 }
cannam@233 288
Chris@434 289 if (blockSize % 2) {
Chris@434 290 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: odd blocksize " << blockSize << " not supported" << std::endl;
cannam@233 291 return false;
cannam@233 292 }
cannam@233 293
cannam@233 294 if (m_channels > 0) {
cannam@233 295 for (int c = 0; c < m_channels; ++c) {
cannam@233 296 delete[] m_freqbuf[c];
cannam@233 297 }
cannam@233 298 delete[] m_freqbuf;
Chris@435 299 delete[] m_ri;
Chris@434 300 if (m_cfg) {
Chris@444 301 Kiss::kiss_fftr_free(m_cfg);
Chris@435 302 m_cfg = 0;
Chris@434 303 delete[] m_cbuf;
Chris@435 304 m_cbuf = 0;
cannam@233 305 }
Chris@317 306 delete m_window;
cannam@233 307 }
cannam@233 308
cannam@288 309 m_stepSize = int(stepSize);
cannam@233 310 m_blockSize = int(blockSize);
cannam@233 311 m_channels = int(channels);
cannam@233 312
cannam@233 313 m_freqbuf = new float *[m_channels];
cannam@233 314 for (int c = 0; c < m_channels; ++c) {
cannam@233 315 m_freqbuf[c] = new float[m_blockSize + 2];
cannam@233 316 }
Chris@444 317 m_ri = new Kiss::kiss_fft_scalar[m_blockSize];
cannam@233 318
Chris@444 319 m_window = new W(convertType(m_windowType), m_blockSize);
cannam@233 320
Chris@444 321 m_cfg = Kiss::kiss_fftr_alloc(m_blockSize, false, 0, 0);
Chris@444 322 m_cbuf = new Kiss::kiss_fft_cpx[m_blockSize/2+1];
cannam@233 323
cannam@288 324 m_processCount = 0;
cannam@288 325
Chris@435 326 return m_plugin->initialise(channels, stepSize, m_blockSize);
cannam@233 327 }
cannam@233 328
cannam@288 329 void
cannam@288 330 PluginInputDomainAdapter::Impl::reset()
cannam@288 331 {
cannam@288 332 m_processCount = 0;
cannam@288 333 m_plugin->reset();
cannam@288 334 }
cannam@288 335
cannam@233 336 size_t
cannam@233 337 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
cannam@233 338 {
cannam@233 339 size_t step = m_plugin->getPreferredStepSize();
cannam@233 340
cannam@233 341 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@233 342 step = getPreferredBlockSize() / 2;
cannam@233 343 }
cannam@233 344
cannam@233 345 return step;
cannam@233 346 }
cannam@233 347
cannam@233 348 size_t
cannam@233 349 PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
cannam@233 350 {
cannam@233 351 size_t block = m_plugin->getPreferredBlockSize();
cannam@233 352
cannam@233 353 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@233 354 if (block == 0) {
cannam@233 355 block = 1024;
cannam@233 356 } else {
cannam@233 357 block = makeBlockSizeAcceptable(block);
cannam@233 358 }
cannam@233 359 }
cannam@233 360
cannam@233 361 return block;
cannam@233 362 }
cannam@233 363
cannam@233 364 size_t
cannam@233 365 PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
cannam@233 366 {
cannam@233 367 if (blockSize < 2) {
cannam@233 368
cannam@283 369 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
cannam@233 370 << "supported, increasing from " << blockSize << " to 2" << std::endl;
cannam@233 371 blockSize = 2;
Chris@434 372
Chris@434 373 } else if (blockSize % 2) {
cannam@233 374
Chris@434 375 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: odd blocksize not" << std::endl
Chris@434 376 << "supported, increasing from " << blockSize << " to " << (blockSize+1) << std::endl;
Chris@434 377 blockSize = blockSize+1;
cannam@233 378 }
cannam@233 379
cannam@233 380 return blockSize;
cannam@233 381 }
cannam@233 382
cannam@233 383 RealTime
cannam@233 384 PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
cannam@233 385 {
cannam@233 386 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 387 return RealTime::zeroTime;
cannam@298 388 } else if (m_method == ShiftData || m_method == NoShift) {
cannam@289 389 return RealTime::zeroTime;
cannam@233 390 } else {
cannam@233 391 return RealTime::frame2RealTime
cannam@233 392 (m_blockSize/2, int(m_inputSampleRate + 0.5));
cannam@233 393 }
cannam@233 394 }
cannam@233 395
cannam@288 396 void
cannam@288 397 PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
cannam@288 398 {
cannam@288 399 m_method = m;
cannam@288 400 }
cannam@288 401
cannam@288 402 PluginInputDomainAdapter::ProcessTimestampMethod
cannam@288 403 PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
cannam@288 404 {
cannam@288 405 return m_method;
cannam@288 406 }
cannam@288 407
Chris@317 408 void
Chris@317 409 PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
Chris@317 410 {
Chris@317 411 if (m_windowType == t) return;
Chris@317 412 m_windowType = t;
Chris@317 413 if (m_window) {
Chris@317 414 delete m_window;
Chris@444 415 m_window = new W(convertType(m_windowType), m_blockSize);
Chris@317 416 }
Chris@317 417 }
Chris@317 418
Chris@317 419 PluginInputDomainAdapter::WindowType
Chris@317 420 PluginInputDomainAdapter::Impl::getWindowType() const
Chris@317 421 {
Chris@317 422 return m_windowType;
Chris@317 423 }
Chris@317 424
Chris@444 425 PluginInputDomainAdapter::Impl::W::WindowType
Chris@317 426 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
Chris@317 427 {
Chris@317 428 switch (t) {
Chris@317 429 case RectangularWindow:
Chris@444 430 return W::RectangularWindow;
Chris@317 431 case BartlettWindow:
Chris@444 432 return W::BartlettWindow;
Chris@317 433 case HammingWindow:
Chris@444 434 return W::HammingWindow;
Chris@317 435 case HanningWindow:
Chris@444 436 return W::HanningWindow;
Chris@317 437 case BlackmanWindow:
Chris@444 438 return W::BlackmanWindow;
Chris@317 439 case NuttallWindow:
Chris@444 440 return W::NuttallWindow;
Chris@317 441 case BlackmanHarrisWindow:
Chris@444 442 return W::BlackmanHarrisWindow;
Chris@319 443 default:
Chris@444 444 return W::HanningWindow;
Chris@317 445 }
Chris@317 446 }
Chris@317 447
cannam@233 448 Plugin::FeatureSet
cannam@233 449 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
cannam@233 450 RealTime timestamp)
cannam@233 451 {
cannam@233 452 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@233 453 return m_plugin->process(inputBuffers, timestamp);
cannam@233 454 }
cannam@233 455
cannam@298 456 if (m_method == ShiftTimestamp || m_method == NoShift) {
cannam@289 457 return processShiftingTimestamp(inputBuffers, timestamp);
cannam@289 458 } else {
cannam@289 459 return processShiftingData(inputBuffers, timestamp);
cannam@289 460 }
cannam@289 461 }
cannam@233 462
cannam@289 463 Plugin::FeatureSet
cannam@289 464 PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
cannam@289 465 RealTime timestamp)
cannam@289 466 {
Chris@421 467 unsigned int roundedRate = 1;
Chris@421 468 if (m_inputSampleRate > 0.f) {
Chris@421 469 roundedRate = (unsigned int)round(m_inputSampleRate);
Chris@421 470 }
Chris@421 471
cannam@298 472 if (m_method == ShiftTimestamp) {
Chris@386 473 // we may need to add one nsec if timestamp +
Chris@386 474 // getTimestampAdjustment() rounds down
cannam@298 475 timestamp = timestamp + getTimestampAdjustment();
Chris@386 476 RealTime nsec(0, 1);
Chris@421 477 if (RealTime::realTime2Frame(timestamp, roundedRate) <
Chris@421 478 RealTime::realTime2Frame(timestamp + nsec, roundedRate)) {
Chris@386 479 timestamp = timestamp + nsec;
Chris@386 480 }
cannam@298 481 }
cannam@233 482
cannam@233 483 for (int c = 0; c < m_channels; ++c) {
cannam@233 484
Chris@317 485 m_window->cut(inputBuffers[c], m_ri);
cannam@233 486
cannam@233 487 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@233 488 // FFT shift
Chris@444 489 Kiss::kiss_fft_scalar value = m_ri[i];
cannam@233 490 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@233 491 m_ri[i + m_blockSize/2] = value;
cannam@233 492 }
cannam@233 493
Chris@444 494 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
Chris@434 495
cannam@233 496 for (int i = 0; i <= m_blockSize/2; ++i) {
Chris@434 497 m_freqbuf[c][i * 2] = m_cbuf[i].r;
Chris@434 498 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
cannam@233 499 }
cannam@233 500 }
cannam@233 501
cannam@289 502 return m_plugin->process(m_freqbuf, timestamp);
cannam@288 503 }
cannam@288 504
cannam@288 505 Plugin::FeatureSet
cannam@289 506 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
cannam@289 507 RealTime timestamp)
cannam@288 508 {
cannam@289 509 if (m_processCount == 0) {
cannam@289 510 if (!m_shiftBuffers) {
cannam@289 511 m_shiftBuffers = new float *[m_channels];
cannam@289 512 for (int c = 0; c < m_channels; ++c) {
cannam@289 513 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
cannam@289 514 }
cannam@289 515 }
cannam@289 516 for (int c = 0; c < m_channels; ++c) {
cannam@289 517 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 518 m_shiftBuffers[c][i] = 0.f;
cannam@289 519 }
cannam@289 520 }
cannam@289 521 }
cannam@289 522
cannam@289 523 for (int c = 0; c < m_channels; ++c) {
cannam@289 524 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
cannam@289 525 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
cannam@289 526 }
cannam@289 527 for (int i = 0; i < m_blockSize; ++i) {
cannam@289 528 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
cannam@289 529 }
cannam@289 530 }
cannam@289 531
cannam@289 532 for (int c = 0; c < m_channels; ++c) {
cannam@289 533
Chris@317 534 m_window->cut(m_shiftBuffers[c], m_ri);
cannam@289 535
cannam@289 536 for (int i = 0; i < m_blockSize/2; ++i) {
cannam@289 537 // FFT shift
Chris@444 538 Kiss::kiss_fft_scalar value = m_ri[i];
cannam@289 539 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@289 540 m_ri[i + m_blockSize/2] = value;
cannam@289 541 }
cannam@289 542
Chris@444 543 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
Chris@434 544
cannam@289 545 for (int i = 0; i <= m_blockSize/2; ++i) {
Chris@434 546 m_freqbuf[c][i * 2] = m_cbuf[i].r;
Chris@434 547 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
cannam@289 548 }
cannam@289 549 }
cannam@289 550
cannam@289 551 ++m_processCount;
cannam@289 552
cannam@289 553 return m_plugin->process(m_freqbuf, timestamp);
cannam@233 554 }
cannam@233 555
cannam@233 556 }
cannam@233 557
cannam@233 558 }
cannam@233 559
cannam@263 560 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
cannam@263 561