comparison vampyhost.cpp @ 12:d0d91312e5a2

Prepare attempt to build using VamPy structures
author Chris Cannam
date Thu, 20 Nov 2014 13:03:50 +0000
parents d29c25695f5e
children 8565ec421f9c
comparison
equal deleted inserted replaced
7:d29c25695f5e 12:d0d91312e5a2
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 2
3 //include for python extension module: must be first 3 //include for python extension module: must be first
4 #include <Python.h> 4 #include <Python.h>
5 #include <vampyhost.h> 5 #include <vampyhost.h>
6 #include <pyRealTime.h> 6
7 #include <PyRealTime.h>
7 8
8 //!!! NB all our NumPy stuff is currently using the deprecated API -- 9 //!!! NB all our NumPy stuff is currently using the deprecated API --
9 //!!! need to work out how to update this 10 //!!! need to work out how to update this
10 #include "numpy/arrayobject.h" 11 //#include "numpy/arrayobject.h"
12
13 #define HAVE_NUMPY 1 // Required
14
15 #include "PyTypeConversions.h"
11 16
12 //includes for vamp host 17 //includes for vamp host
13 #include "vamp-hostsdk/Plugin.h" 18 #include "vamp-hostsdk/Plugin.h"
14 #include "vamp-hostsdk/PluginHostAdapter.h" 19 #include "vamp-hostsdk/PluginHostAdapter.h"
15 #include "vamp-hostsdk/PluginChannelAdapter.h" 20 #include "vamp-hostsdk/PluginChannelAdapter.h"
410 plugDesc->isInitialised = true; 415 plugDesc->isInitialised = true;
411 416
412 return Py_True; 417 return Py_True;
413 } 418 }
414 419
415 // These conversion functions are borrowed from PyTypeInterface in VamPy
416
417 template<typename RET, typename DTYPE>
418 static
419 RET *pyArrayConvert(char* raw_data_ptr, long length, size_t strides)
420 {
421 RET *rValue = new RET[length];
422
423 /// check if the array is continuous, if not use strides info
424 if (sizeof(DTYPE)!=strides) {
425 char* data = (char*) raw_data_ptr;
426 for (long i = 0; i<length; ++i){
427 rValue[i] = (RET)(*((DTYPE*)data));
428 data += strides;
429 }
430 return rValue;
431 }
432
433 DTYPE* data = (DTYPE*) raw_data_ptr;
434 for (long i = 0; i<length; ++i){
435 rValue[i] = (RET)data[i];
436 }
437
438 return rValue;
439 }
440
441 static float *
442 pyArrayToFloatArray(PyObject *pyValue)
443 {
444 if (!PyArray_Check(pyValue)) {
445 cerr << "pyArrayToFloatArray: Failed, object has no array interface" << endl;
446 return 0;
447 }
448
449 PyArrayObject* pyArray = (PyArrayObject*) pyValue;
450 PyArray_Descr* descr = pyArray->descr;
451
452 /// check raw data and descriptor pointers
453 if (pyArray->data == 0 || descr == 0) {
454 cerr << "pyArrayToFloatArray: Failed, NumPy array has NULL data or descriptor" << endl;
455 return 0;
456 }
457
458 /// check dimensions
459 if (pyArray->nd != 1) {
460 cerr << "pyArrayToFloatArray: Failed, NumPy array is multi-dimensional" << endl;
461 return 0;
462 }
463
464 /// check strides (useful if array is not continuous)
465 size_t strides = *((size_t*) pyArray->strides);
466
467 /// convert the array
468 switch (descr->type_num) {
469 case NPY_FLOAT : // dtype='float32'
470 return pyArrayConvert<float,float>(pyArray->data,pyArray->dimensions[0],strides);
471 case NPY_DOUBLE : // dtype='float64'
472 return pyArrayConvert<float,double>(pyArray->data,pyArray->dimensions[0],strides);
473 default:
474 cerr << "pyArrayToFloatArray: Failed: Unsupported value type " << descr->type_num << " in NumPy array object (only float32, float64 supported)" << endl;
475 return 0;
476 }
477 }
478
479
480 /* RUN PROCESS */ 420 /* RUN PROCESS */
481 421
482 static PyObject * 422 static PyObject *
483 vampyhost_process(PyObject *self, PyObject *args) 423 vampyhost_process(PyObject *self, PyObject *args)
484 { 424 {
512 if (!pd->isInitialised) { 452 if (!pd->isInitialised) {
513 PyErr_SetString(PyExc_StandardError, 453 PyErr_SetString(PyExc_StandardError,
514 "Plugin has not been initialised."); 454 "Plugin has not been initialised.");
515 return NULL; } 455 return NULL; }
516 456
517 size_t channels = pd->channels; 457 int channels = pd->channels;
518 size_t blockSize = pd->blockSize; 458 // int blockSize = pd->blockSize;
519 459
520 if (!PyList_Check(pyBuffer)) { 460 if (!PyList_Check(pyBuffer)) {
521 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); 461 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
522 return NULL; 462 return NULL;
523 } 463 }
528 return NULL; 468 return NULL;
529 } 469 }
530 470
531 float **inbuf = new float *[channels]; 471 float **inbuf = new float *[channels];
532 472
473 PyTypeConversions typeConv;
474 typeConv.setNumpyInstalled(true);
475
476 vector<vector<float> > data;
533 for (int c = 0; c < channels; ++c) { 477 for (int c = 0; c < channels; ++c) {
534 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c); 478 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
535 inbuf[c] = pyArrayToFloatArray(cbuf); 479 data.push_back(typeConv.PyArray_To_FloatVector(cbuf));
536 if (!inbuf[c]) { 480 }
537 PyErr_SetString(PyExc_TypeError,"NumPy Array required for each channel in process input."); 481
538 return NULL; 482 for (int c = 0; c < channels; ++c) {
539 } 483 inbuf[c] = &data[c][0];
540 } 484 }
541 485
542 RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime); 486 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
543 487
544 //Call process and store the output 488 //Call process and store the output
545 pd->output = plugin->process(inbuf, timeStamp); 489 pd->output = plugin->process(inbuf, timeStamp);
546 490
547 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */ 491 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
548 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ... 492 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
549 493
550
551 for (int c = 0; c < channels; ++c){
552 delete[] inbuf[c];
553 }
554 delete[] inbuf; 494 delete[] inbuf;
555 495
556 return NULL; //!!! Need to return actual features! 496 return NULL; //!!! Need to return actual features!
557 497
558 } 498 }
671 611
672 {"getOutput", vampyhost_getOutput, METH_VARARGS, 612 {"getOutput", vampyhost_getOutput, METH_VARARGS,
673 xx_foo_doc}, 613 xx_foo_doc},
674 614
675 /* Add RealTime Module Methods */ 615 /* Add RealTime Module Methods */
676 616 /*
677 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS, 617 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
678 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")}, 618 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
679 619
680 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS, 620 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
681 PyDoc_STR("realtime() -> returns new RealTime object")}, 621 PyDoc_STR("realtime() -> returns new RealTime object")},
682 622 */
683 {NULL, NULL} /* sentinel */ 623 {NULL, NULL} /* sentinel */
684 }; 624 };
685 625
686 //Documentation for our new module 626 //Documentation for our new module
687 PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); 627 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");