annotate vamp-hostsdk/PluginInputDomainAdapter.cpp @ 56:4ab6224110ef host-factory-stuff

* implement plugin loader and plugin input-domain adapter (to do basic ffts)
author cannam
date Fri, 04 May 2007 15:21:12 +0000
parents
children 09a1aac6c362
rev   line source
cannam@56 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@56 2
cannam@56 3 /*
cannam@56 4 Vamp
cannam@56 5
cannam@56 6 An API for audio analysis and feature extraction plugins.
cannam@56 7
cannam@56 8 Centre for Digital Music, Queen Mary, University of London.
cannam@56 9 Copyright 2006 Chris Cannam.
cannam@56 10
cannam@56 11 Permission is hereby granted, free of charge, to any person
cannam@56 12 obtaining a copy of this software and associated documentation
cannam@56 13 files (the "Software"), to deal in the Software without
cannam@56 14 restriction, including without limitation the rights to use, copy,
cannam@56 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@56 16 of the Software, and to permit persons to whom the Software is
cannam@56 17 furnished to do so, subject to the following conditions:
cannam@56 18
cannam@56 19 The above copyright notice and this permission notice shall be
cannam@56 20 included in all copies or substantial portions of the Software.
cannam@56 21
cannam@56 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@56 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@56 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@56 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@56 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@56 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@56 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@56 29
cannam@56 30 Except as contained in this notice, the names of the Centre for
cannam@56 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@56 32 shall not be used in advertising or otherwise to promote the sale,
cannam@56 33 use or other dealings in this Software without prior written
cannam@56 34 authorization.
cannam@56 35 */
cannam@56 36
cannam@56 37 #include "PluginInputDomainAdapter.h"
cannam@56 38
cannam@56 39 #include <cmath>
cannam@56 40
cannam@56 41 namespace Vamp {
cannam@56 42
cannam@56 43 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
cannam@56 44 Plugin(0),
cannam@56 45 m_plugin(plugin),
cannam@56 46 m_channels(0),
cannam@56 47 m_blockSize(0),
cannam@56 48 m_freqbuf(0)
cannam@56 49 {
cannam@56 50 }
cannam@56 51
cannam@56 52 PluginInputDomainAdapter::~PluginInputDomainAdapter()
cannam@56 53 {
cannam@56 54 delete m_plugin;
cannam@56 55 }
cannam@56 56
cannam@56 57 bool
cannam@56 58 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@56 59 {
cannam@56 60 //!!! complain and die if blocksize is not a power of 2
cannam@56 61
cannam@56 62 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@56 63 if (m_channels > 0) {
cannam@56 64 for (size_t c = 0; c < m_channels; ++c) {
cannam@56 65 delete[] m_freqbuf[c];
cannam@56 66 }
cannam@56 67 delete[] m_freqbuf;
cannam@56 68 delete[] m_ri;
cannam@56 69 delete[] m_ro;
cannam@56 70 delete[] m_io;
cannam@56 71 }
cannam@56 72 }
cannam@56 73
cannam@56 74 m_channels = channels;
cannam@56 75 m_blockSize = blockSize;
cannam@56 76
cannam@56 77 if (m_plugin->getInputDomain() == FrequencyDomain) {
cannam@56 78 m_freqbuf = new float *[m_channels];
cannam@56 79 for (size_t c = 0; c < m_channels; ++c) {
cannam@56 80 m_freqbuf[c] = new float[m_blockSize + 2];
cannam@56 81 }
cannam@56 82 m_ri = new double[m_blockSize];
cannam@56 83 m_ro = new double[m_blockSize];
cannam@56 84 m_io = new double[m_blockSize];
cannam@56 85 }
cannam@56 86
cannam@56 87 return m_plugin->initialise(channels, stepSize, blockSize);
cannam@56 88 }
cannam@56 89
cannam@56 90 void
cannam@56 91 PluginInputDomainAdapter::reset()
cannam@56 92 {
cannam@56 93 m_plugin->reset();
cannam@56 94 }
cannam@56 95
cannam@56 96 unsigned int
cannam@56 97 PluginInputDomainAdapter::getVampApiVersion() const
cannam@56 98 {
cannam@56 99 return m_plugin->getVampApiVersion();
cannam@56 100 }
cannam@56 101
cannam@56 102 std::string
cannam@56 103 PluginInputDomainAdapter::getIdentifier() const
cannam@56 104 {
cannam@56 105 return m_plugin->getIdentifier();
cannam@56 106 }
cannam@56 107
cannam@56 108 std::string
cannam@56 109 PluginInputDomainAdapter::getName() const
cannam@56 110 {
cannam@56 111 return m_plugin->getName();
cannam@56 112 }
cannam@56 113
cannam@56 114 std::string
cannam@56 115 PluginInputDomainAdapter::getDescription() const
cannam@56 116 {
cannam@56 117 return m_plugin->getDescription();
cannam@56 118 }
cannam@56 119
cannam@56 120 std::string
cannam@56 121 PluginInputDomainAdapter::getMaker() const
cannam@56 122 {
cannam@56 123 return m_plugin->getMaker();
cannam@56 124 }
cannam@56 125
cannam@56 126 int
cannam@56 127 PluginInputDomainAdapter::getPluginVersion() const
cannam@56 128 {
cannam@56 129 return m_plugin->getPluginVersion();
cannam@56 130 }
cannam@56 131
cannam@56 132 std::string
cannam@56 133 PluginInputDomainAdapter::getCopyright() const
cannam@56 134 {
cannam@56 135 return m_plugin->getCopyright();
cannam@56 136 }
cannam@56 137
cannam@56 138 PluginBase::ParameterList
cannam@56 139 PluginInputDomainAdapter::getParameterDescriptors() const
cannam@56 140 {
cannam@56 141 return m_plugin->getParameterDescriptors();
cannam@56 142 }
cannam@56 143
cannam@56 144 float
cannam@56 145 PluginInputDomainAdapter::getParameter(std::string parameter) const
cannam@56 146 {
cannam@56 147 return m_plugin->getParameter(parameter);
cannam@56 148 }
cannam@56 149
cannam@56 150 void
cannam@56 151 PluginInputDomainAdapter::setParameter(std::string parameter, float value)
cannam@56 152 {
cannam@56 153 m_plugin->setParameter(parameter, value);
cannam@56 154 }
cannam@56 155
cannam@56 156 PluginBase::ProgramList
cannam@56 157 PluginInputDomainAdapter::getPrograms() const
cannam@56 158 {
cannam@56 159 return m_plugin->getPrograms();
cannam@56 160 }
cannam@56 161
cannam@56 162 std::string
cannam@56 163 PluginInputDomainAdapter::getCurrentProgram() const
cannam@56 164 {
cannam@56 165 return m_plugin->getCurrentProgram();
cannam@56 166 }
cannam@56 167
cannam@56 168 void
cannam@56 169 PluginInputDomainAdapter::selectProgram(std::string program)
cannam@56 170 {
cannam@56 171 m_plugin->selectProgram(program);
cannam@56 172 }
cannam@56 173
cannam@56 174 size_t
cannam@56 175 PluginInputDomainAdapter::getPreferredStepSize() const
cannam@56 176 {
cannam@56 177 size_t step = m_plugin->getPreferredStepSize();
cannam@56 178
cannam@56 179 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@56 180 step = getPreferredBlockSize() / 2;
cannam@56 181 }
cannam@56 182
cannam@56 183 return step;
cannam@56 184 }
cannam@56 185
cannam@56 186 size_t
cannam@56 187 PluginInputDomainAdapter::getPreferredBlockSize() const
cannam@56 188 {
cannam@56 189 size_t block = m_plugin->getPreferredBlockSize();
cannam@56 190
cannam@56 191 if (block == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
cannam@56 192 block = 1024;
cannam@56 193 }
cannam@56 194
cannam@56 195 return block;
cannam@56 196 }
cannam@56 197
cannam@56 198 size_t
cannam@56 199 PluginInputDomainAdapter::getMinChannelCount() const
cannam@56 200 {
cannam@56 201 return m_plugin->getMinChannelCount();
cannam@56 202 }
cannam@56 203
cannam@56 204 size_t PluginInputDomainAdapter::getMaxChannelCount() const
cannam@56 205 {
cannam@56 206 return m_plugin->getMaxChannelCount();
cannam@56 207 }
cannam@56 208
cannam@56 209 Plugin::OutputList
cannam@56 210 PluginInputDomainAdapter::getOutputDescriptors() const
cannam@56 211 {
cannam@56 212 return m_plugin->getOutputDescriptors();
cannam@56 213 }
cannam@56 214
cannam@56 215 Plugin::FeatureSet
cannam@56 216 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
cannam@56 217 {
cannam@56 218 if (m_plugin->getInputDomain() == TimeDomain) {
cannam@56 219 return m_plugin->process(inputBuffers, timestamp);
cannam@56 220 }
cannam@56 221
cannam@56 222 for (size_t c = 0; c < m_channels; ++c) {
cannam@56 223
cannam@56 224 for (size_t i = 0; i < m_blockSize; ++i) {
cannam@56 225 // Hanning window
cannam@56 226 m_ri[i] = double(inputBuffers[c][i])
cannam@56 227 * (0.50 - 0.50 * cos((2 * M_PI * i)
cannam@56 228 / m_blockSize));
cannam@56 229 }
cannam@56 230
cannam@56 231 for (size_t i = 0; i < m_blockSize/2; ++i) {
cannam@56 232 // FFT shift
cannam@56 233 double value = m_ri[i];
cannam@56 234 m_ri[i] = m_ri[i + m_blockSize/2];
cannam@56 235 m_ri[i + m_blockSize/2] = value;
cannam@56 236 }
cannam@56 237
cannam@56 238 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
cannam@56 239
cannam@56 240 for (size_t i = 0; i < m_blockSize/2; ++i) {
cannam@56 241 m_freqbuf[c][i * 2] = m_ro[i];
cannam@56 242 m_freqbuf[c][i * 2 + 1] = m_io[i];
cannam@56 243 }
cannam@56 244 }
cannam@56 245
cannam@56 246 //!!! do we want to adjust the timestamp or anything so as to
cannam@56 247 // effectively centre the frame?
cannam@56 248
cannam@56 249 return m_plugin->process(m_freqbuf, timestamp);
cannam@56 250 }
cannam@56 251
cannam@56 252 Plugin::FeatureSet
cannam@56 253 PluginInputDomainAdapter::getRemainingFeatures()
cannam@56 254 {
cannam@56 255 return m_plugin->getRemainingFeatures();
cannam@56 256 }
cannam@56 257
cannam@56 258 void
cannam@56 259 PluginInputDomainAdapter::fft(unsigned int n, bool inverse,
cannam@56 260 double *ri, double *ii, double *ro, double *io)
cannam@56 261 {
cannam@56 262 if (!ri || !ro || !io) return;
cannam@56 263
cannam@56 264 unsigned int bits;
cannam@56 265 unsigned int i, j, k, m;
cannam@56 266 unsigned int blockSize, blockEnd;
cannam@56 267
cannam@56 268 double tr, ti;
cannam@56 269
cannam@56 270 if (n < 2) return;
cannam@56 271 if (n & (n-1)) return;
cannam@56 272
cannam@56 273 double angle = 2.0 * M_PI;
cannam@56 274 if (inverse) angle = -angle;
cannam@56 275
cannam@56 276 for (i = 0; ; ++i) {
cannam@56 277 if (n & (1 << i)) {
cannam@56 278 bits = i;
cannam@56 279 break;
cannam@56 280 }
cannam@56 281 }
cannam@56 282
cannam@56 283 static unsigned int tableSize = 0;
cannam@56 284 static int *table = 0;
cannam@56 285
cannam@56 286 if (tableSize != n) {
cannam@56 287
cannam@56 288 delete[] table;
cannam@56 289
cannam@56 290 table = new int[n];
cannam@56 291
cannam@56 292 for (i = 0; i < n; ++i) {
cannam@56 293
cannam@56 294 m = i;
cannam@56 295
cannam@56 296 for (j = k = 0; j < bits; ++j) {
cannam@56 297 k = (k << 1) | (m & 1);
cannam@56 298 m >>= 1;
cannam@56 299 }
cannam@56 300
cannam@56 301 table[i] = k;
cannam@56 302 }
cannam@56 303
cannam@56 304 tableSize = n;
cannam@56 305 }
cannam@56 306
cannam@56 307 if (ii) {
cannam@56 308 for (i = 0; i < n; ++i) {
cannam@56 309 ro[table[i]] = ri[i];
cannam@56 310 io[table[i]] = ii[i];
cannam@56 311 }
cannam@56 312 } else {
cannam@56 313 for (i = 0; i < n; ++i) {
cannam@56 314 ro[table[i]] = ri[i];
cannam@56 315 io[table[i]] = 0.0;
cannam@56 316 }
cannam@56 317 }
cannam@56 318
cannam@56 319 blockEnd = 1;
cannam@56 320
cannam@56 321 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
cannam@56 322
cannam@56 323 double delta = angle / (double)blockSize;
cannam@56 324 double sm2 = -sin(-2 * delta);
cannam@56 325 double sm1 = -sin(-delta);
cannam@56 326 double cm2 = cos(-2 * delta);
cannam@56 327 double cm1 = cos(-delta);
cannam@56 328 double w = 2 * cm1;
cannam@56 329 double ar[3], ai[3];
cannam@56 330
cannam@56 331 for (i = 0; i < n; i += blockSize) {
cannam@56 332
cannam@56 333 ar[2] = cm2;
cannam@56 334 ar[1] = cm1;
cannam@56 335
cannam@56 336 ai[2] = sm2;
cannam@56 337 ai[1] = sm1;
cannam@56 338
cannam@56 339 for (j = i, m = 0; m < blockEnd; j++, m++) {
cannam@56 340
cannam@56 341 ar[0] = w * ar[1] - ar[2];
cannam@56 342 ar[2] = ar[1];
cannam@56 343 ar[1] = ar[0];
cannam@56 344
cannam@56 345 ai[0] = w * ai[1] - ai[2];
cannam@56 346 ai[2] = ai[1];
cannam@56 347 ai[1] = ai[0];
cannam@56 348
cannam@56 349 k = j + blockEnd;
cannam@56 350 tr = ar[0] * ro[k] - ai[0] * io[k];
cannam@56 351 ti = ar[0] * io[k] + ai[0] * ro[k];
cannam@56 352
cannam@56 353 ro[k] = ro[j] - tr;
cannam@56 354 io[k] = io[j] - ti;
cannam@56 355
cannam@56 356 ro[j] += tr;
cannam@56 357 io[j] += ti;
cannam@56 358 }
cannam@56 359 }
cannam@56 360
cannam@56 361 blockEnd = blockSize;
cannam@56 362 }
cannam@56 363
cannam@56 364 if (inverse) {
cannam@56 365
cannam@56 366 double denom = (double)n;
cannam@56 367
cannam@56 368 for (i = 0; i < n; i++) {
cannam@56 369 ro[i] /= denom;
cannam@56 370 io[i] /= denom;
cannam@56 371 }
cannam@56 372 }
cannam@56 373 }
cannam@56 374
cannam@56 375
cannam@56 376 }
cannam@56 377