annotate vampyhost.cpp @ 11:e5b575d69b01 lf-numpy-arrays

changed a comment
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Wed, 20 Mar 2013 11:07:24 +0000
parents 8306b7fdd2d0
children
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 //include for python extension module: must be first
Chris@0 4 #include <Python.h>
Chris@0 5 #include <vampyhost.h>
Chris@0 6 #include <pyRealTime.h>
Chris@0 7
Chris@4 8 //!!! NB all our NumPy stuff is currently using the deprecated API --
Chris@4 9 //!!! need to work out how to update this
Chris@4 10 #include "numpy/arrayobject.h"
Chris@4 11
Chris@0 12 //includes for vamp host
Chris@1 13 #include "vamp-hostsdk/Plugin.h"
Chris@1 14 #include "vamp-hostsdk/PluginHostAdapter.h"
Chris@1 15 #include "vamp-hostsdk/PluginChannelAdapter.h"
Chris@1 16 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
Chris@1 17 #include "vamp-hostsdk/PluginLoader.h"
Chris@0 18 //#include "vamp/vamp.h"
Chris@0 19
Chris@0 20 #include <iostream>
Chris@0 21 #include <fstream>
Chris@0 22 #include <set>
Chris@0 23 #include <sndfile.h>
Chris@0 24
Chris@0 25 #include <cstring>
Chris@0 26 #include <cstdlib>
Chris@0 27 #include <string>
Chris@0 28
Chris@0 29 #include "system.h"
Chris@0 30
Chris@0 31 #include <cmath>
Chris@0 32
Chris@0 33
Chris@0 34 using namespace std;
Chris@0 35 using namespace Vamp;
Chris@0 36
Chris@0 37 using Vamp::Plugin;
Chris@0 38 using Vamp::PluginHostAdapter;
Chris@0 39 using Vamp::RealTime;
Chris@0 40 using Vamp::HostExt::PluginLoader;
Chris@0 41
Chris@0 42 #define HOST_VERSION "1.1"
Chris@0 43
Chris@0 44
Chris@0 45 /* MODULE HELPER FUNCTIONS */
Chris@2 46 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
Chris@0 47
Chris@0 48 /*obtain C plugin handle and key from pyCobject */
luis@7 49 bool getPluginHandle
Chris@0 50 (PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) {
Chris@0 51
Chris@0 52 //char errormsg[]="Wrong input argument: Plugin Handle required.";
Chris@0 53
Chris@0 54 *plugin = NULL;
Chris@2 55 if (!PyCObject_Check(pyPluginHandle)) return false;
Chris@0 56
Chris@0 57 //try to convert to Plugin pointer
Chris@0 58 Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle);
luis@7 59 if (!p) return false;
Chris@0 60
Chris@0 61 string pId;
Chris@0 62
Chris@0 63 if (pKey) {
Chris@0 64 *pKey = (string*) PyCObject_GetDesc(pyPluginHandle);
Chris@2 65 if (!*pKey) return false;
Chris@0 66 pId = *(string*) *pKey;
Chris@0 67
Chris@0 68 } else {
Chris@0 69
Chris@0 70 void *pKey = PyCObject_GetDesc(pyPluginHandle);
Chris@2 71 if (!pKey) return false;
Chris@0 72 pId = *(string*) pKey;
Chris@0 73 }
luis@7 74
Chris@0 75 string::size_type pos = pId.find(':');
Chris@2 76 if (pos == string::npos) return false;
Chris@0 77
Chris@0 78 pId = pId.substr(pId.rfind(':')+1);
luis@7 79 string identifier = p->getIdentifier();
luis@7 80
Chris@2 81 if (pId.compare(identifier)) return false;
Chris@0 82
Chris@0 83 *plugin = p;
Chris@0 84 return true;
Chris@0 85 }
Chris@0 86
Chris@0 87 /*
Chris@0 88 ----------------------------------------------------------------
Chris@0 89 */
Chris@0 90
Chris@0 91
Chris@0 92
Chris@0 93 /*
luis@7 94 VAMPYHOST MAIN
luis@7 95 ---------------------------------------------------------------------
Chris@0 96 */
Chris@0 97
Chris@0 98 /* ENUMERATE PLUGINS*/
Chris@0 99
Chris@0 100 static PyObject *
Chris@0 101 vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
Chris@0 102 {
Chris@0 103 string retType;
luis@7 104
Chris@0 105 if (!PyArg_ParseTuple(args, "|s:enumeratePlugins", &retType))
Chris@0 106 return NULL;
Chris@0 107
Chris@0 108 //list available plugins
Chris@0 109 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 110 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
Chris@0 111
Chris@0 112 //library Map
Chris@0 113 typedef multimap<string, PluginLoader::PluginKey> LibraryMap;
Chris@0 114 LibraryMap libraryMap;
Chris@0 115
Chris@0 116 //New list object
Chris@0 117 PyObject *pyList = PyList_New(plugins.size());
Chris@0 118
Chris@0 119 for (size_t i = 0; i < plugins.size(); ++i) {
Chris@0 120 string path = loader->getLibraryPathForPlugin(plugins[i]);
Chris@0 121 libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
Chris@0 122
Chris@0 123 PyObject *pyPluginKey = PyString_FromString(plugins[i].c_str());
Chris@0 124 PyList_SET_ITEM(pyList,i,pyPluginKey);
luis@7 125
Chris@0 126 }
Chris@0 127
Chris@0 128 PyList_Sort(pyList);
Chris@0 129 return pyList;
Chris@0 130 }
Chris@0 131
Chris@0 132
Chris@0 133 /* GET PLUGIN LIBRARY PATH*/
Chris@0 134
Chris@0 135 static PyObject *
Chris@0 136 vampyhost_getLibraryPath(PyObject *self, PyObject *args)
Chris@0 137 {
Chris@0 138 PyObject *pyPluginKey;
Chris@0 139
Chris@0 140 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@0 141 PyErr_SetString(PyExc_TypeError,
Chris@0 142 "String input argument required: pluginKey");
Chris@0 143 return NULL; }
Chris@0 144
Chris@0 145 //convert to stl string
Chris@0 146 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 147
Chris@0 148 //check pluginKey Validity
Chris@0 149 string::size_type ki = pluginKey.find(':');
Chris@0 150 if (ki == string::npos) {
Chris@0 151 PyErr_SetString(PyExc_TypeError,
luis@7 152 "String input argument required: pluginLibrary:Identifier");
Chris@0 153 return NULL;
Chris@0 154 }
Chris@0 155
Chris@0 156 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 157 string path = loader->getLibraryPathForPlugin(pluginKey);
Chris@0 158 PyObject *pyPath = PyString_FromString(path.c_str());
Chris@0 159 return pyPath;
Chris@0 160 }
Chris@0 161
Chris@0 162
Chris@0 163 /* GET PLUGIN CATEGORY*/
Chris@0 164
Chris@0 165 static PyObject *
Chris@0 166 vampyhost_getPluginCategory(PyObject *self, PyObject *args)
Chris@0 167 {
Chris@0 168 PyObject *pyPluginKey;
Chris@0 169
Chris@0 170 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@0 171 PyErr_SetString(PyExc_TypeError,
Chris@0 172 "String input argument required: pluginKey");
Chris@0 173 return NULL; }
Chris@0 174
Chris@0 175 //convert to stl string
Chris@0 176 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 177
Chris@0 178 //check pluginKey Validity
Chris@0 179 string::size_type ki = pluginKey.find(':');
Chris@0 180 if (ki == string::npos) {
Chris@0 181 PyErr_SetString(PyExc_TypeError,
luis@7 182 "String input argument required: pluginLibrary:Identifier");
Chris@0 183 return NULL;
Chris@0 184 }
Chris@0 185
Chris@0 186 PluginLoader *loader = PluginLoader::getInstance();
luis@7 187 PluginLoader::PluginCategoryHierarchy
Chris@0 188 category = loader->getPluginCategory(pluginKey);
Chris@0 189 string catstring;
Chris@0 190
Chris@0 191 if (!category.empty()) {
Chris@0 192 catstring = "";
Chris@0 193 for (size_t ci = 0; ci < category.size(); ++ci) {
Chris@0 194 catstring.append(category[ci]);
Chris@0 195 catstring.append(" ");
Chris@0 196 }
Chris@0 197 PyObject *pyCat = PyString_FromString(catstring.c_str());
Chris@0 198 return pyCat;
Chris@0 199 }
Chris@0 200 PyObject *pyCat = PyString_FromString("");
Chris@0 201 return pyCat;
Chris@0 202 }
Chris@0 203
Chris@0 204
Chris@0 205
Chris@0 206 /* GET PLUGIN OUTPUT LIST*/
Chris@0 207
Chris@0 208 static PyObject *
Chris@0 209 vampyhost_getOutputList(PyObject *self, PyObject *args)
Chris@0 210 {
Chris@0 211 PyObject *pyPluginHandle;
Chris@0 212 string pluginKey;
Chris@0 213
Chris@0 214 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
Chris@0 215 PyErr_SetString(PyExc_TypeError,
Chris@0 216 "Invalid argument: plugin handle or plugin key required.");
luis@7 217 return NULL;
Chris@0 218 }
Chris@0 219
Chris@0 220 //check if we have a plugin key string or a handle object
Chris@0 221 if (PyString_Check(pyPluginHandle) ) {
Chris@0 222
Chris@0 223 pluginKey.assign(PyString_AS_STRING(pyPluginHandle));
Chris@0 224 //check pluginKey Validity
Chris@0 225 string::size_type ki = pluginKey.find(':');
Chris@0 226 if (ki == string::npos) {
Chris@0 227 PyErr_SetString(PyExc_TypeError,
luis@7 228 "String input argument required: pluginLibrary:Identifier");
Chris@0 229 return NULL;
Chris@0 230 }
Chris@0 231
Chris@0 232 } else {
luis@7 233
luis@7 234 string *key;
luis@7 235 Plugin *plugin;
Chris@0 236
Chris@0 237 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 238 PyErr_SetString(PyExc_TypeError,
Chris@0 239 "Invalid or deleted plugin handle.");
Chris@0 240 return NULL; }
Chris@0 241 pluginKey.assign(*key);
luis@7 242 }
luis@7 243
Chris@0 244 //This code creates new instance of the plugin anyway
Chris@0 245 PluginLoader *loader = PluginLoader::getInstance();
luis@7 246
Chris@0 247 //load plugin
Chris@3 248 Plugin *plugin = loader->loadPlugin
Chris@3 249 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
luis@7 250 if (!plugin) {
Chris@0 251 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
luis@7 252 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 253 return NULL;
luis@7 254 }
Chris@0 255
Chris@0 256 Plugin::OutputList outputs = plugin->getOutputDescriptors();
Chris@0 257 //Plugin::OutputDescriptor od;
Chris@0 258
Chris@0 259 if (outputs.size()<1) {
Chris@0 260 string pyerr("Plugin has no output: "); pyerr += pluginKey;
luis@7 261 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 262 return NULL;
Chris@0 263 }
Chris@0 264
Chris@0 265 //New list object
Chris@0 266 PyObject *pyList = PyList_New(outputs.size());
Chris@0 267
Chris@0 268 for (size_t i = 0; i < outputs.size(); ++i) {
luis@7 269 PyObject *pyOutputId =
Chris@0 270 PyString_FromString(outputs[i].identifier.c_str());
luis@7 271 PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 272 }
Chris@0 273
Chris@0 274 delete plugin;
Chris@0 275 return pyList;
Chris@0 276 }
Chris@0 277
Chris@0 278
Chris@0 279
Chris@0 280 /* LOAD PLUGIN */
Chris@0 281
Chris@0 282 static PyObject *
Chris@0 283 vampyhost_loadPlugin(PyObject *self, PyObject *args)
Chris@0 284 {
Chris@0 285 PyObject *pyPluginKey;
Chris@0 286 float inputSampleRate;
Chris@0 287
luis@7 288 if (!PyArg_ParseTuple(args, "Sf",
Chris@0 289 &pyPluginKey,
Chris@0 290 &inputSampleRate)) {
Chris@0 291 PyErr_SetString(PyExc_TypeError,
Chris@0 292 "String input argument required: pluginKey");
Chris@0 293 return NULL; }
Chris@0 294
Chris@0 295 //convert to stl string
Chris@0 296 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 297
Chris@0 298 //check pluginKey Validity
Chris@0 299 string::size_type ki = pluginKey.find(':');
Chris@0 300 if (ki == string::npos) {
Chris@0 301 PyErr_SetString(PyExc_TypeError,
luis@7 302 "String input argument required: pluginLibrary:Identifier");
Chris@0 303 return NULL;
Chris@0 304 }
Chris@0 305
Chris@0 306 PluginLoader *loader = PluginLoader::getInstance();
luis@7 307
Chris@0 308 //load plugin
luis@7 309 Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate,
Chris@6 310 PluginLoader::ADAPT_ALL_SAFE);
luis@7 311 if (!plugin) {
Chris@0 312 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
luis@7 313 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 314 return NULL;
luis@7 315 }
Chris@0 316 //void *identifier = (void*) new string(pluginKey);
Chris@0 317 PyPluginDescriptor *pd = new PyPluginDescriptor;
luis@7 318
Chris@0 319 pd->key = pluginKey;
Chris@0 320 pd->isInitialised = false;
Chris@0 321 pd->inputSampleRate = inputSampleRate;
luis@7 322
Chris@0 323 //New PyCObject
luis@7 324 //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
luis@7 325 //(void*) plugin, identifier, NULL);
Chris@0 326
luis@7 327 PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
luis@7 328 (void*) plugin, (void*) pd, NULL);
luis@7 329
Chris@0 330 return pyPluginHandle;
Chris@0 331 }
Chris@0 332
Chris@0 333
Chris@0 334
Chris@0 335 /* UNLOAD PLUGIN */
Chris@0 336
Chris@0 337 static PyObject *
Chris@0 338 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
Chris@0 339 {
Chris@0 340 PyObject *pyPluginHandle;
Chris@0 341
Chris@0 342 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
Chris@0 343 PyErr_SetString(PyExc_TypeError,
Chris@0 344 "Wrong input argument: Plugin Handle required.");
Chris@0 345 return NULL; }
Chris@0 346
luis@7 347 string *key;
luis@7 348 Plugin *plugin;
Chris@0 349
Chris@0 350 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 351 PyErr_SetString(PyExc_TypeError,
Chris@0 352 "Invalid or already deleted plugin handle.");
Chris@0 353 return NULL; }
Chris@0 354
Chris@0 355 /* Prevent repeated calls from causing segfault
Chris@0 356 sice it will fail type checking the 2nd time: */
Chris@0 357 PyCObject_SetVoidPtr(pyPluginHandle,NULL);
luis@7 358
Chris@0 359 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
luis@7 360
Chris@0 361 delete plugin;
Chris@0 362 delete pd;
Chris@0 363 return pyPluginHandle;
Chris@0 364
Chris@0 365 }
Chris@0 366
Chris@0 367
Chris@0 368 /* INITIALISE PLUGIN */
Chris@0 369
Chris@0 370 static PyObject *
Chris@0 371 vampyhost_initialise(PyObject *self, PyObject *args)
Chris@0 372 {
Chris@0 373 PyObject *pyPluginHandle;
luis@7 374 size_t channels, blockSize, stepSize;
Chris@0 375
luis@7 376 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle,
luis@7 377 (size_t) &channels,
luis@7 378 (size_t) &stepSize,
luis@7 379 (size_t) &blockSize))
Chris@0 380 {
Chris@0 381 PyErr_SetString(PyExc_TypeError,
Chris@0 382 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
luis@7 383 return NULL;
Chris@0 384 }
Chris@0 385
luis@7 386 Plugin *plugin;
luis@7 387 string *key;
Chris@0 388
Chris@0 389 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 390 PyErr_SetString(PyExc_TypeError,
Chris@0 391 "Invalid plugin handle.");
Chris@0 392 return NULL; }
Chris@0 393
Chris@0 394 // here we cast the void pointer as PyPluginDescriptor instead of string
luis@7 395 PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;
Chris@0 396
Chris@0 397 plugDesc->channels = channels;
Chris@0 398 plugDesc->stepSize = stepSize;
Chris@0 399 plugDesc->blockSize = blockSize;
Chris@3 400
Chris@0 401 if (!plugin->initialise(channels, stepSize, blockSize)) {
Chris@6 402 std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl;
Chris@0 403 PyErr_SetString(PyExc_TypeError,
Chris@0 404 "Plugin initialization failed.");
Chris@6 405 return NULL;
Chris@6 406 }
Chris@0 407
luis@7 408 plugDesc->identifier =
Chris@0 409 plugDesc->key.substr(plugDesc->key.rfind(':')+1);
Chris@0 410 plugDesc->isInitialised = true;
luis@7 411
Chris@0 412 return Py_True;
Chris@0 413 }
Chris@0 414
Chris@4 415 // These conversion functions are borrowed from PyTypeInterface in VamPy
Chris@4 416
Chris@4 417 template<typename RET, typename DTYPE>
Chris@4 418 static
Chris@4 419 RET *pyArrayConvert(char* raw_data_ptr, long length, size_t strides)
Chris@4 420 {
Chris@4 421 RET *rValue = new RET[length];
luis@7 422
Chris@4 423 /// check if the array is continuous, if not use strides info
Chris@4 424 if (sizeof(DTYPE)!=strides) {
Chris@4 425 char* data = (char*) raw_data_ptr;
Chris@4 426 for (long i = 0; i<length; ++i){
Chris@4 427 rValue[i] = (RET)(*((DTYPE*)data));
Chris@4 428 data += strides;
Chris@4 429 }
Chris@4 430 return rValue;
Chris@4 431 }
Chris@4 432
Chris@4 433 DTYPE* data = (DTYPE*) raw_data_ptr;
Chris@4 434 for (long i = 0; i<length; ++i){
Chris@4 435 rValue[i] = (RET)data[i];
Chris@4 436 }
luis@7 437
Chris@4 438 return rValue;
Chris@4 439 }
Chris@4 440
Chris@4 441 static float *
Chris@4 442 pyArrayToFloatArray(PyObject *pyValue)
Chris@4 443 {
Chris@4 444 if (!PyArray_Check(pyValue)) {
Chris@4 445 cerr << "pyArrayToFloatArray: Failed, object has no array interface" << endl;
Chris@4 446 return 0;
luis@7 447 }
Chris@4 448
Chris@4 449 PyArrayObject* pyArray = (PyArrayObject*) pyValue;
Chris@4 450 PyArray_Descr* descr = pyArray->descr;
luis@7 451
Chris@4 452 /// check raw data and descriptor pointers
Chris@4 453 if (pyArray->data == 0 || descr == 0) {
Chris@4 454 cerr << "pyArrayToFloatArray: Failed, NumPy array has NULL data or descriptor" << endl;
Chris@4 455 return 0;
Chris@4 456 }
Chris@4 457
Chris@4 458 /// check dimensions
Chris@4 459 if (pyArray->nd != 1) {
Chris@4 460 cerr << "pyArrayToFloatArray: Failed, NumPy array is multi-dimensional" << endl;
Chris@4 461 return 0;
Chris@4 462 }
Chris@4 463
Chris@4 464 /// check strides (useful if array is not continuous)
Chris@4 465 size_t strides = *((size_t*) pyArray->strides);
luis@7 466
Chris@4 467 /// convert the array
Chris@4 468 switch (descr->type_num) {
Chris@4 469 case NPY_FLOAT : // dtype='float32'
Chris@4 470 return pyArrayConvert<float,float>(pyArray->data,pyArray->dimensions[0],strides);
Chris@4 471 case NPY_DOUBLE : // dtype='float64'
Chris@4 472 return pyArrayConvert<float,double>(pyArray->data,pyArray->dimensions[0],strides);
Chris@4 473 default:
Chris@4 474 cerr << "pyArrayToFloatArray: Failed: Unsupported value type " << descr->type_num << " in NumPy array object (only float32, float64 supported)" << endl;
Chris@4 475 return 0;
Chris@4 476 }
Chris@4 477 }
Chris@4 478
Chris@0 479
Chris@0 480 /* RUN PROCESS */
Chris@0 481
Chris@0 482 static PyObject *
Chris@0 483 vampyhost_process(PyObject *self, PyObject *args)
Chris@0 484 {
Chris@0 485 PyObject *pyPluginHandle;
luis@8 486 PyArrayObject *pyBuffer;
Chris@0 487 PyObject *pyRealTime;
Chris@0 488
luis@7 489 if (!PyArg_ParseTuple(args, "OOO",
Chris@0 490 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
luis@8 491 &pyBuffer, // Audio data (NumPy ndim array)
Chris@0 492 &pyRealTime)) { // TimeStamp
Chris@0 493 PyErr_SetString(PyExc_TypeError,
Chris@0 494 "Required: plugin handle, buffer, timestmap.");
Chris@0 495 return NULL; }
Chris@0 496
Chris@0 497 if (!PyRealTime_Check(pyRealTime)) {
Chris@0 498 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
Chris@0 499 return NULL; }
Chris@0 500
Chris@4 501 string *key;
luis@7 502 Plugin *plugin;
Chris@0 503
Chris@4 504 if (!getPluginHandle(pyPluginHandle, &plugin, &key)) {
luis@8 505 PyErr_SetString(PyExc_AttributeError,
luis@8 506 "Invalid or already deleted plugin handle.");
luis@8 507 return NULL;
Chris@4 508 }
Chris@0 509
Chris@0 510 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 511
Chris@0 512 if (!pd->isInitialised) {
luis@8 513 PyErr_SetString(PyExc_StandardError,
luis@8 514 "Plugin has not been initialised.");
luis@8 515 return NULL; }
Chris@0 516
luis@7 517 size_t channels = pd->channels;
Chris@0 518 size_t blockSize = pd->blockSize;
Chris@0 519
luis@8 520 if (!PyArray_Check(pyBuffer)) {
luis@8 521 PyErr_SetString(PyExc_TypeError, "Argument is not a Numpy array.");
Chris@4 522 return NULL;
Chris@0 523 }
Chris@0 524
luis@8 525 if (pyBuffer->nd != channels) {
luis@8 526 cerr << "Wrong number of channels: got " << pyBuffer->nd << ", expected " << channels << endl;
Chris@4 527 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
Chris@4 528 return NULL;
Chris@4 529 }
Chris@0 530
luis@8 531 int n = pyBuffer->dimensions[0];
luis@8 532 int m = pyBuffer->dimensions[1];
luis@8 533
luis@10 534 // Domain Type, either Vamp::Plugin::FrequencyDomain
luis@10 535 // or Vamp::Plugin::TimeDomain
luis@10 536 Vamp::Plugin::InputDomain dtype = plugin->getInputDomain();
luis@10 537
luis@8 538 cout << "Kind :" << pyBuffer->descr->kind << endl;
luis@8 539 cout << "Strides 0 :" << pyBuffer->strides[0] << endl;
luis@8 540 cout << "Strides 1 :" << pyBuffer->strides[1] << endl;
luis@8 541 cout << "Flags:" << pyBuffer->flags << endl;
luis@8 542
luis@10 543 cout << "Input Domain" << dtype << endl;
luis@10 544 cout << "Plugin Maker" << plugin->getMaker() << endl;
luis@10 545
Chris@4 546 float **inbuf = new float *[channels];
luis@8 547 cout << "Created inbuf with #channels: " << channels << endl;
Chris@0 548
luis@11 549
luis@11 550
Chris@4 551 for (int c = 0; c < channels; ++c) {
luis@8 552
luis@8 553 // cout << "[Host] Converting channel #" << c << endl;
luis@8 554 // PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
luis@8 555 // cout << "Ok1..." << endl;
luis@8 556 // inbuf[c] = pyArrayToFloatArray(cbuf);
luis@8 557
luis@8 558 inbuf[c] = pyArrayToFloatArray((PyObject*) pyBuffer);
luis@8 559
luis@11 560 cout << "Converted " << endl;
luis@8 561
Chris@4 562 if (!inbuf[c]) {
Chris@4 563 PyErr_SetString(PyExc_TypeError,"NumPy Array required for each channel in process input.");
Chris@4 564 return NULL;
Chris@0 565 }
luis@8 566
luis@8 567 cout << "[Host] Converted channel #" << c << endl;
luis@8 568
Chris@4 569 }
Chris@0 570
Chris@0 571 RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime);
Chris@0 572
luis@8 573 cout << "[Host] Gonna call plugin->process" << endl;
luis@8 574
Chris@0 575 //Call process and store the output
Chris@4 576 pd->output = plugin->process(inbuf, timeStamp);
Chris@0 577
luis@8 578 cout << "[Host] Called plugin->process" << endl;
luis@8 579
Chris@0 580 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
luis@9 581 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
Chris@0 582
luis@10 583
luis@10 584 size_t featListOutLength = pd->output.size();
luis@10 585
luis@10 586 //New PyList for the featurelist
luis@10 587 PyObject *pyFeatureList = PyList_New(featListOutLength);
luis@10 588
luis@10 589 PyArrayObject *aaaa;
luis@10 590
luis@10 591 npy_intp *dims[2];
luis@10 592
luis@10 593 // Plugin::FeatureList features = pd->output[0];
luis@10 594
luis@9 595 // Loop FeatureLists
luis@9 596 for(int i = 0; i < pd->output.size(); i++ ){
luis@10 597 //New PyList for the features
luis@10 598 size_t outLength = pd->output[i].size();
luis@10 599 PyObject *pyFeatureList = PyList_New(outLength);
luis@10 600
luis@9 601 cout << "FeatureList #" << i << " has size " << pd->output[i].size() << endl;
luis@9 602
luis@9 603 // loop Features
luis@9 604 for(int j = 0; j < pd->output[i].size(); j++ ){
luis@10 605
luis@10 606 // debug - printing some features
luis@9 607 cout << "Feature #" << j << endl;
luis@9 608 cout << " Label: " << pd->output[i][j].label << endl;
luis@9 609 cout << " hasTimestamp? " << pd->output[i][j].hasTimestamp << endl;
luis@9 610 cout << " hasDuration? " << pd->output[i][j].hasDuration << endl;
luis@9 611 cout << " values.size " << pd->output[i][j].values.size() << endl;
luis@9 612 cout << " values[0] " << pd->output[i][j].values[0] << endl;
luis@9 613 }
luis@9 614 }
luis@9 615
luis@9 616
luis@10 617 // Gonna print just one
luis@9 618
luis@10 619 size_t arraySize = pd->output[0][0].values.size();
luis@10 620 PyObject *pySampleList = PyList_New((Py_ssize_t) arraySize);
luis@10 621 PyObject **pySampleListArray = PySequence_Fast_ITEMS(pySampleList);
luis@10 622
luis@10 623 for (size_t idx = 0; idx < arraySize; ++idx) {
luis@10 624 PyObject *pyFloat=PyFloat_FromDouble((double) pd->output[0][0].values[idx]);
luis@10 625 pySampleListArray[idx] = pyFloat;
luis@10 626 }
Chris@0 627
Chris@4 628 for (int c = 0; c < channels; ++c){
Chris@4 629 delete[] inbuf[c];
Chris@0 630 }
Chris@4 631 delete[] inbuf;
Chris@0 632
luis@10 633 return PyArray_Return((PyArrayObject*) pySampleList);
luis@10 634 // return pySampleList;
luis@10 635
luis@10 636 // return pyFeatureList; //!!! Need to return actual features!
Chris@0 637 }
Chris@0 638
Chris@0 639 /* GET / SET OUTPUT */
Chris@0 640
Chris@0 641 //getOutput(plugin,outputNo)
Chris@0 642 static PyObject *
Chris@0 643 vampyhost_getOutput(PyObject *self, PyObject *args) {
Chris@0 644
Chris@0 645 PyObject *pyPluginHandle;
Chris@0 646 // PyObject *pyBuffer;
Chris@0 647 // PyObject *pyRealTime;
Chris@0 648 PyObject *pyOutput;
Chris@0 649
luis@7 650 if (!PyArg_ParseTuple(args, "OO",
Chris@0 651 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
Chris@0 652 &pyOutput)) { // Output reference
Chris@0 653 PyErr_SetString(PyExc_TypeError,
Chris@0 654 "Required: plugin handle, buffer, timestmap.");
Chris@0 655 return NULL; }
Chris@0 656
luis@7 657 string *key;
luis@7 658 Plugin *plugin;
Chris@0 659
Chris@0 660 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 661 PyErr_SetString(PyExc_AttributeError,
Chris@0 662 "Invalid or already deleted plugin handle.");
Chris@0 663 return NULL; }
Chris@0 664
Chris@0 665 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 666
Chris@0 667 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
Chris@0 668
Chris@0 669 //Get output list: but we don't need it
Chris@0 670 //Plugin::FeatureList features = pd->output[outputNo];
Chris@0 671
Chris@0 672 size_t outLength = pd->output[outputNo].size();
Chris@0 673
Chris@0 674 //New PyList for the featurelist
Chris@0 675 PyObject *pyFeatureList = PyList_New(outLength);
Chris@0 676
Chris@0 677 for (size_t i = 0; i < outLength; ++i) {
Chris@0 678 // Test:
Chris@0 679 /*
luis@7 680 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type);
Chris@0 681 if (pyFeature == NULL) break; //return NULL;
Chris@0 682
Chris@0 683 pyFeature->x_attr = NULL;
Chris@0 684 pyFeature->feature = &pd->output[outputNo][i];
Chris@0 685
luis@7 686 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);
Chris@0 687 */
Chris@0 688 }
Chris@0 689
Chris@0 690 Py_INCREF(pyFeatureList);
Chris@0 691 return pyFeatureList;
Chris@0 692
Chris@0 693 // EXPLAIN WHAT WE NEED TO DO HERE:
Chris@0 694 // We have the block output in pd->output
luis@7 695 // FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v
luis@7 696 // Vamp::Plugin::FeatureSet output; = pd->output
Chris@0 697 // typedef std::vector<Feature> FeatureList;
Chris@0 698 // typedef std::map<int, FeatureList> FeatureSet; // key is output no
Chris@0 699
luis@7 700 // THIS IS FOR OUTPUT id LOOKUP LATER
Chris@0 701 // Plugin::OutputList outputs = plugin->getOutputDescriptors();
luis@7 702 //
Chris@0 703 // if (outputs.size()<1) {
Chris@0 704 // string pyerr("Plugin has no output: "); pyerr += pluginKey;
luis@7 705 // PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 706 // return NULL;
Chris@0 707 // }
luis@7 708 //
Chris@0 709 // //New list object
Chris@0 710 // PyObject *pyList = PyList_New(outputs.size());
luis@7 711 //
Chris@0 712 // for (size_t i = 0; i < outputs.size(); ++i) {
luis@7 713 // PyObject *pyOutputId =
Chris@0 714 // PyString_FromString(outputs[i].identifier.c_str());
luis@7 715 // PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 716 // }
luis@7 717
Chris@0 718 }
Chris@0 719
Chris@0 720
Chris@0 721
Chris@0 722
Chris@0 723 /* List of functions defined in this module */
Chris@0 724 //module methods table
Chris@0 725 static PyMethodDef vampyhost_methods[] = {
Chris@0 726
Chris@0 727 {"enumeratePlugins", vampyhost_enumeratePlugins, METH_VARARGS,
Chris@0 728 xx_foo_doc},
Chris@0 729
Chris@0 730 {"getLibraryPath", vampyhost_getLibraryPath, METH_VARARGS,
Chris@0 731 xx_foo_doc},
Chris@0 732
Chris@0 733 {"getPluginCategory", vampyhost_getPluginCategory, METH_VARARGS,
Chris@0 734 xx_foo_doc},
Chris@0 735
Chris@0 736 {"getOutputList", vampyhost_getOutputList, METH_VARARGS,
Chris@0 737 xx_foo_doc},
Chris@0 738
Chris@0 739 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
Chris@0 740 xx_foo_doc},
Chris@0 741
Chris@0 742 {"process", vampyhost_process, METH_VARARGS,
Chris@0 743 xx_foo_doc},
Chris@0 744
Chris@0 745 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS,
Chris@0 746 xx_foo_doc},
Chris@0 747
Chris@0 748 {"initialise", vampyhost_initialise, METH_VARARGS,
Chris@0 749 xx_foo_doc},
Chris@0 750
Chris@0 751 {"getOutput", vampyhost_getOutput, METH_VARARGS,
Chris@0 752 xx_foo_doc},
Chris@0 753
Chris@0 754 /* Add RealTime Module Methods */
Chris@0 755
Chris@0 756 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
Chris@0 757 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
Chris@0 758
Chris@0 759 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
Chris@0 760 PyDoc_STR("realtime() -> returns new RealTime object")},
luis@7 761
Chris@0 762 {NULL, NULL} /* sentinel */
Chris@0 763 };
Chris@0 764
Chris@0 765 //Documentation for our new module
Chris@0 766 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
Chris@0 767
Chris@0 768 /* Initialization function for the module (*must* be called initxx) */
Chris@0 769
Chris@0 770 //module initialization (includes extern C {...} as necessary)
Chris@0 771 PyMODINIT_FUNC
Chris@0 772 initvampyhost(void)
Chris@0 773 {
Chris@0 774 PyObject *m;
Chris@0 775
Chris@0 776 /* Finalize the type object including setting type of the new type
luis@7 777 * object; doing it here is required for portability to Windows
Chris@0 778 * without requiring C++. */
Chris@0 779
Chris@0 780 if (PyType_Ready(&RealTime_Type) < 0)
Chris@0 781 return;
Chris@0 782 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
Chris@0 783
Chris@0 784 /* Create the module and add the functions */
Chris@0 785 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
Chris@0 786 if (m == NULL) return;
Chris@0 787
luis@8 788 // Numpy array library initialization function
luis@8 789 import_array();
luis@8 790
Chris@0 791 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
Chris@0 792
Chris@0 793 }