changeset 52:b56513f872a5

Move files into subdirs
author Chris Cannam
date Wed, 14 Jan 2015 08:30:47 +0000
parents a78b14c41c74
children 808cc721b313
files .hgignore FloatConversion.h Makefile.inc PyPluginObject.cpp PyPluginObject.h PyRealTime.cpp PyRealTime.h VectorConversion.cpp VectorConversion.h native/FloatConversion.h native/PyPluginObject.cpp native/PyPluginObject.h native/PyRealTime.cpp native/PyRealTime.h native/VectorConversion.cpp native/VectorConversion.h native/vampyhost-junk.cpp native/vampyhost.cpp test/test_metadata.py test/test_plugin_metadata.py test/test_process.py test_metadata.py test_plugin_metadata.py test_process.py vampyhost-junk.cpp vampyhost.cpp
diffstat 26 files changed, 2431 insertions(+), 2424 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jan 13 12:16:38 2015 +0000
+++ b/.hgignore	Wed Jan 14 08:30:47 2015 +0000
@@ -5,3 +5,5 @@
 *.dll
 *.dylib
 *.pyc
+*.bak
+*.orig
--- a/FloatConversion.h	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-  VampyHost
-
-  Use Vamp audio analysis plugins in Python
-
-  Gyorgy Fazekas and Chris Cannam
-  Centre for Digital Music, Queen Mary, University of London
-  Copyright 2008-2014 Queen Mary, University of London
-  
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation
-  files (the "Software"), to deal in the Software without
-  restriction, including without limitation the rights to use, copy,
-  modify, merge, publish, distribute, sublicense, and/or sell copies
-  of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-  Except as contained in this notice, the names of the Centre for
-  Digital Music; Queen Mary, University of London; and the authors
-  shall not be used in advertising or otherwise to promote the sale,
-  use or other dealings in this Software without prior written
-  authorization.
-*/
-
-#ifndef VAMPYHOST_FLOAT_CONVERSION_H
-#define VAMPYHOST_FLOAT_CONVERSION_H
-
-class FloatConversion
-{
-public:
-    static bool check(PyObject *pyValue) {
-	if (pyValue && PyFloat_Check(pyValue)) {
-	    return true;
-	}
-	if (pyValue && PyLong_Check(pyValue)) {
-	    return true;
-	}
-	if (pyValue && PyInt_Check(pyValue)) {
-	    return true;
-	}
-	return false;
-    }
-	
-    static float convert(PyObject* pyValue) {
-	
-	if (pyValue && PyFloat_Check(pyValue)) {
-	    return (float) PyFloat_AS_DOUBLE(pyValue);
-	}
-
-	if (pyValue && PyLong_Check(pyValue)) {
-	    return (float) PyLong_AsDouble(pyValue);
-	}
-
-	if (pyValue && PyInt_Check(pyValue)) {
-	    return (float) PyInt_AsLong(pyValue);
-	}
-
-	return 0.0;
-    }
-};
-
-#endif
-
--- a/Makefile.inc	Tue Jan 13 12:16:38 2015 +0000
+++ b/Makefile.inc	Wed Jan 14 08:30:47 2015 +0000
@@ -4,8 +4,10 @@
 CXX		?= g++
 CC		?= gcc
 
-HEADERS		:= PyPluginObject.h PyRealTime.h FloatConversion.h VectorConversion.h
-SOURCES		:= PyPluginObject.cpp PyRealTime.cpp VectorConversion.cpp vampyhost.cpp
+SRC_DIR		:= native
+
+HEADERS		:= $(SRC_DIR)/PyPluginObject.h $(SRC_DIR)/PyRealTime.h $(SRC_DIR)/FloatConversion.h $(SRC_DIR)/VectorConversion.h
+SOURCES		:= $(SRC_DIR)/PyPluginObject.cpp $(SRC_DIR)/PyRealTime.cpp $(SRC_DIR)/VectorConversion.cpp $(SRC_DIR)/vampyhost.cpp
 
 OBJECTS		:= $(SOURCES:.cpp=.o)
 OBJECTS		:= $(OBJECTS:.c=.o)
@@ -24,6 +26,9 @@
 
 # DO NOT DELETE
 
-PyRealTime.o: PyRealTime.h
-vampyhost.o: PyRealTime.h VectorConversion.h
-VectorConversion.o: VectorConversion.h
+native/PyPluginObject.o: native/PyPluginObject.h native/FloatConversion.h
+native/PyPluginObject.o: native/VectorConversion.h native/PyRealTime.h
+native/PyRealTime.o: native/PyRealTime.h
+native/VectorConversion.o: native/FloatConversion.h native/VectorConversion.h
+native/vampyhost.o: native/PyRealTime.h native/PyPluginObject.h
+native/vampyhost.o: native/VectorConversion.h
--- a/PyPluginObject.cpp	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,725 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    VampyHost
-
-    Use Vamp audio analysis plugins in Python
-
-    Gyorgy Fazekas and Chris Cannam
-    Centre for Digital Music, Queen Mary, University of London
-    Copyright 2008-2014 Queen Mary, University of London
-  
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and the authors
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#include "PyPluginObject.h"
-
-// define a unique API pointer 
-#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#define NO_IMPORT_ARRAY
-#include "numpy/arrayobject.h"
-
-#include "structmember.h"
-
-#include "FloatConversion.h"
-#include "VectorConversion.h"
-#include "PyRealTime.h"
-
-#include <string>
-#include <vector>
-#include <cstddef>
-#include <set>
-
-using namespace std;
-using namespace Vamp;
-
-static
-PyPluginObject *
-getPluginObject(PyObject *pyPluginHandle)
-{
-    PyPluginObject *pd = 0;
-    if (PyPlugin_Check(pyPluginHandle)) {
-        pd = (PyPluginObject *)pyPluginHandle;
-    }
-    if (!pd || !pd->plugin) {
-        PyErr_SetString(PyExc_AttributeError,
-                        "Invalid or already deleted plugin handle.");
-        return 0;
-    } else {
-        return pd;
-    }
-}
-
-static
-PyObject *
-pystr(const string &s)
-{
-    return PyString_FromString(s.c_str());
-}
-
-PyObject *
-PyPluginObject_From_Plugin(Plugin *plugin)
-{
-    PyPluginObject *pd = 
-        (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0);
-    pd->plugin = plugin;
-    pd->isInitialised = false;
-    pd->channels = 0;
-    pd->blockSize = 0;
-    pd->stepSize = 0;
-
-    PyObject *infodict = PyDict_New();
-    PyDict_SetItemString
-        (infodict, "apiVersion", PyInt_FromLong(plugin->getVampApiVersion()));
-    PyDict_SetItemString
-        (infodict, "pluginVersion", PyInt_FromLong(plugin->getPluginVersion()));
-    PyDict_SetItemString
-        (infodict, "identifier", pystr(plugin->getIdentifier()));
-    PyDict_SetItemString
-        (infodict, "name", pystr(plugin->getName()));
-    PyDict_SetItemString
-        (infodict, "description", pystr(plugin->getDescription()));
-    PyDict_SetItemString
-        (infodict, "maker", pystr(plugin->getMaker()));
-    PyDict_SetItemString
-        (infodict, "copyright", pystr(plugin->getCopyright()));
-    pd->info = infodict;
-
-    pd->inputDomain = plugin->getInputDomain();
-
-    VectorConversion conv;
-
-    Plugin::ParameterList pl = plugin->getParameterDescriptors();
-    PyObject *params = PyList_New(pl.size());
-    
-    for (int i = 0; i < (int)pl.size(); ++i) {
-        PyObject *paramdict = PyDict_New();
-        PyDict_SetItemString
-            (paramdict, "identifier", pystr(pl[i].identifier));
-        PyDict_SetItemString
-            (paramdict, "name", pystr(pl[i].name));
-        PyDict_SetItemString
-            (paramdict, "description", pystr(pl[i].description));
-        PyDict_SetItemString
-            (paramdict, "unit", pystr(pl[i].unit));
-        PyDict_SetItemString
-            (paramdict, "minValue", PyFloat_FromDouble(pl[i].minValue));
-        PyDict_SetItemString
-            (paramdict, "maxValue", PyFloat_FromDouble(pl[i].maxValue));
-        PyDict_SetItemString
-            (paramdict, "defaultValue", PyFloat_FromDouble(pl[i].defaultValue));
-        if (pl[i].isQuantized) {
-            PyDict_SetItemString
-                (paramdict, "isQuantized", Py_True);
-            PyDict_SetItemString
-                (paramdict, "quantizeStep", PyFloat_FromDouble(pl[i].quantizeStep));
-            if (!pl[i].valueNames.empty()) {
-                PyDict_SetItemString
-                    (paramdict, "valueNames", conv.PyValue_From_StringVector(pl[i].valueNames));
-            }
-        } else {
-            PyDict_SetItemString
-                (paramdict, "isQuantized", Py_False);
-        }
-        
-        PyList_SET_ITEM(params, i, paramdict);
-    }
-
-    pd->parameters = params;
-
-    Plugin::ProgramList prl = plugin->getPrograms();
-    PyObject *progs = PyList_New(prl.size());
-
-    for (int i = 0; i < (int)prl.size(); ++i) {
-        PyList_SET_ITEM(progs, i, pystr(prl[i]));
-    }
-
-    pd->programs = progs;
-    
-    return (PyObject *)pd;
-}
-
-static void
-PyPluginObject_dealloc(PyPluginObject *self)
-{
-    delete self->plugin;
-    PyObject_Del(self);
-}
-
-static PyObject *
-getOutputs(PyObject *self, PyObject *args)
-{ 
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    Plugin::OutputList ol = pd->plugin->getOutputDescriptors();
-    PyObject *outputs = PyList_New(ol.size());
-    
-    for (int i = 0; i < (int)ol.size(); ++i) {
-        PyObject *outdict = PyDict_New();
-        PyDict_SetItemString
-            (outdict, "identifier", pystr(ol[i].identifier));
-        PyDict_SetItemString
-            (outdict, "name", pystr(ol[i].name));
-        PyDict_SetItemString
-            (outdict, "description", pystr(ol[i].description));
-        PyDict_SetItemString
-            (outdict, "binCount", PyInt_FromLong(ol[i].binCount));
-        if (ol[i].binCount > 0) {
-            if (ol[i].hasKnownExtents) {
-                PyDict_SetItemString
-                    (outdict, "hasKnownExtents", Py_True);
-                PyDict_SetItemString
-                    (outdict, "minValue", PyFloat_FromDouble(ol[i].minValue));
-                PyDict_SetItemString
-                    (outdict, "maxValue", PyFloat_FromDouble(ol[i].maxValue));
-            } else {
-                PyDict_SetItemString
-                    (outdict, "hasKnownExtents", Py_False);
-            }
-            if (ol[i].isQuantized) {
-                PyDict_SetItemString
-                    (outdict, "isQuantized", Py_True);
-                PyDict_SetItemString
-                    (outdict, "quantizeStep", PyFloat_FromDouble(ol[i].quantizeStep));
-            } else {
-                PyDict_SetItemString
-                    (outdict, "isQuantized", Py_False);
-            }
-        }
-        PyDict_SetItemString
-            (outdict, "sampleType", PyInt_FromLong((int)ol[i].sampleType));
-        PyDict_SetItemString
-            (outdict, "sampleRate", PyFloat_FromDouble(ol[i].sampleRate));
-        PyDict_SetItemString
-            (outdict, "hasDuration", ol[i].hasDuration ? Py_True : Py_False);
-        
-        PyList_SET_ITEM(outputs, i, outdict);
-    }
-
-    return outputs;
-}
-
-static PyObject *
-initialise(PyObject *self, PyObject *args)
-{
-    size_t channels, blockSize, stepSize;
-
-    if (!PyArg_ParseTuple (args, "nnn",
-                           (size_t) &channels,
-                           (size_t) &stepSize,
-                           (size_t) &blockSize)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "initialise() takes channel count, step size, and block size arguments");
-        return 0;
-    }
-
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    pd->channels = channels;
-    pd->stepSize = stepSize;
-    pd->blockSize = blockSize;
-
-    if (!pd->plugin->initialise(channels, stepSize, blockSize)) {
-        cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << endl;
-        PyErr_SetString(PyExc_TypeError,
-                        "Plugin initialization failed");
-        return 0;
-    }
-
-    pd->isInitialised = true;
-
-    return Py_True;
-}
-
-static PyObject *
-reset(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    if (!pd->isInitialised) {
-        PyErr_SetString(PyExc_StandardError,
-                        "Plugin has not been initialised");
-        return 0;
-    }
-        
-    pd->plugin->reset();
-    return Py_True;
-}
-
-static bool
-hasParameter(PyPluginObject *pd, string id)
-{
-    PluginBase::ParameterList pl = pd->plugin->getParameterDescriptors();
-    for (int i = 0; i < (int)pl.size(); ++i) {
-        if (pl[i].identifier == id) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static PyObject *
-getParameterValue(PyObject *self, PyObject *args)
-{
-    PyObject *pyParam;
-
-    if (!PyArg_ParseTuple(args, "S", &pyParam)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "getParameterValue() takes parameter id (string) argument");
-        return 0; }
-
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    string param = PyString_AS_STRING(pyParam);
-    
-    if (!hasParameter(pd, param)) {
-        PyErr_SetString(PyExc_StandardError,
-                        (string("Unknown parameter id \"") + param + "\"").c_str());
-        return 0;
-    }
-    
-    float value = pd->plugin->getParameter(param);
-    return PyFloat_FromDouble(double(value));
-}
-
-static PyObject *
-setParameterValue(PyObject *self, PyObject *args)
-{
-    PyObject *pyParam;
-    float value;
-
-    if (!PyArg_ParseTuple(args, "Sf", &pyParam, &value)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "setParameterValue() takes parameter id (string), and value (float) arguments");
-        return 0; }
-
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    string param = PyString_AS_STRING(pyParam);
-    
-    if (!hasParameter(pd, param)) {
-        PyErr_SetString(PyExc_StandardError,
-                        (string("Unknown parameter id \"") + param + "\"").c_str());
-        return 0;
-    }
-
-    pd->plugin->setParameter(param, value);
-    return Py_True;
-}
-
-static PyObject *
-setParameterValues(PyObject *self, PyObject *args)
-{
-    PyObject *dict;
-
-    if (!PyArg_ParseTuple(args, "O", &dict)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "setParameterValues() takes dict argument");
-        return 0; }
-
-    if (!PyDict_Check(dict)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "setParameterValues() takes dict argument");
-        return 0; }
-    
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    PluginBase::ParameterList pl = pd->plugin->getParameterDescriptors();
-    set<string> paramIds;
-    for (int i = 0; i < (int)pl.size(); ++i) {
-        paramIds.insert(pl[i].identifier);
-    }
-
-    Py_ssize_t pos = 0;
-    PyObject *key, *value;
-    while (PyDict_Next(dict, &pos, &key, &value)) {
-        if (!key || !PyString_CheckExact(key)) {
-            PyErr_SetString(PyExc_TypeError,
-                            "Parameter dict keys must all have string type");
-            return 0;
-        }
-        if (!value || !FloatConversion::check(value)) {
-            PyErr_SetString(PyExc_TypeError,
-                            "Parameter dict values must be convertible to float");
-            return 0;
-        }
-        string param = PyString_AS_STRING(key);
-        if (paramIds.find(param) == paramIds.end()) {
-            PyErr_SetString(PyExc_StandardError,
-                            (string("Unknown parameter id \"") + param + "\"").c_str());
-            return 0;
-        }
-        pd->plugin->setParameter(param, FloatConversion::convert(value));
-    }
-    
-    return Py_True;
-}
-
-static PyObject *
-selectProgram(PyObject *self, PyObject *args)
-{
-    PyObject *pyParam;
-
-    if (!PyArg_ParseTuple(args, "S", &pyParam)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "selectProgram() takes parameter id (string) argument");
-        return 0; }
-
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    pd->plugin->selectProgram(PyString_AS_STRING(pyParam));
-    return Py_True;
-}
-
-static
-PyObject *
-convertFeatureSet(const Plugin::FeatureSet &fs)
-{
-    VectorConversion conv;
-    
-    PyObject *pyFs = PyDict_New();
-
-    for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
-         fsi != fs.end(); ++fsi) {
-
-        int fno = fsi->first;
-        const Plugin::FeatureList &fl = fsi->second;
-
-        if (!fl.empty()) {
-
-            PyObject *pyFl = PyList_New(fl.size());
-
-            for (int fli = 0; fli < (int)fl.size(); ++fli) {
-
-                const Plugin::Feature &f = fl[fli];
-                PyObject *pyF = PyDict_New();
-
-                if (f.hasTimestamp) {
-                    PyDict_SetItemString
-                        (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp));
-                }
-                if (f.hasDuration) {
-                    PyDict_SetItemString
-                        (pyF, "duration", PyRealTime_FromRealTime(f.duration));
-                }
-
-                PyDict_SetItemString
-                    (pyF, "label", pystr(f.label));
-
-                if (!f.values.empty()) {
-                    PyDict_SetItemString
-                        (pyF, "values", conv.PyArray_From_FloatVector(f.values));
-                }
-
-                PyList_SET_ITEM(pyFl, fli, pyF);
-            }
-
-            PyObject *pyN = PyInt_FromLong(fno);
-            PyDict_SetItem(pyFs, pyN, pyFl);
-        }
-    }
-    
-    return pyFs;
-}
-
-static vector<vector<float> >
-convertPluginInput(PyObject *pyBuffer, int channels, int blockSize)
-{
-    vector<vector<float> > data;
-
-    VectorConversion conv;
-
-    if (PyArray_CheckExact(pyBuffer)) {
-
-        data = conv.Py2DArray_To_FloatVector(pyBuffer);
-
-        if (conv.error) {
-            PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
-            return data;
-        }
-
-        if ((int)data.size() != channels) {
-//            cerr << "Wrong number of channels: got " << data.size() << ", expected " << channels << endl;
-            PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
-            return vector<vector<float> >();
-        }
-        
-    } else {
-        
-        if (!PyList_Check(pyBuffer)) {
-            PyErr_SetString(PyExc_TypeError, "List of NumPy arrays or lists of numbers required for process input");
-            return data;
-        }
-        
-        if (PyList_GET_SIZE(pyBuffer) != channels) {
-//            cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
-            PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
-            return data;
-        }
-
-        for (int c = 0; c < channels; ++c) {
-            PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
-            data.push_back(conv.PyValue_To_FloatVector(cbuf));
-            if (conv.error) {
-                PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
-                return vector<vector<float> >();
-            }
-        }
-    }
-    
-    for (int c = 0; c < channels; ++c) {
-        if ((int)data[c].size() != blockSize) {
-//            cerr << "Wrong number of samples on channel " << c << ": expected " << blockSize << " (plugin's block size), got " << data[c].size() << endl;
-            PyErr_SetString(PyExc_TypeError, "Wrong number of samples for process block");
-            return vector<vector<float> >();
-        }
-    }
-    
-    return data;
-}
-
-static PyObject *
-process(PyObject *self, PyObject *args)
-{
-    PyObject *pyBuffer;
-    PyObject *pyRealTime;
-
-    if (!PyArg_ParseTuple(args, "OO",
-                          &pyBuffer,                    // Audio data
-                          &pyRealTime)) {               // TimeStamp
-        PyErr_SetString(PyExc_TypeError,
-                        "process() takes buffer (2D array or list of arrays, one row per channel) and timestamp (RealTime) arguments");
-        return 0; }
-
-    if (!PyRealTime_Check(pyRealTime)) {
-        PyErr_SetString(PyExc_TypeError, "Valid timestamp required.");
-        return 0; }
-
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    if (!pd->isInitialised) {
-        PyErr_SetString(PyExc_StandardError,
-                        "Plugin has not been initialised.");
-        return 0;
-    }
-
-    int channels = pd->channels;
-    vector<vector<float> > data =
-        convertPluginInput(pyBuffer, channels, pd->blockSize);
-    if (data.empty()) return 0;
-
-    float **inbuf = new float *[channels];
-    for (int c = 0; c < channels; ++c) {
-        inbuf[c] = &data[c][0];
-    }
-    RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
-    Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
-    delete[] inbuf;
-
-    return convertFeatureSet(fs);
-}
-
-static PyObject *
-getRemainingFeatures(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    if (!pd->isInitialised) {
-        PyErr_SetString(PyExc_StandardError,
-                        "Plugin has not been initialised.");
-        return 0;
-    }
-
-    Plugin::FeatureSet fs = pd->plugin->getRemainingFeatures();
-
-    return convertFeatureSet(fs);
-}
-
-static PyObject *
-getPreferredBlockSize(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-    return PyInt_FromLong(pd->plugin->getPreferredBlockSize());
-}
-
-static PyObject *
-getPreferredStepSize(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-    return PyInt_FromLong(pd->plugin->getPreferredStepSize());
-}
-
-static PyObject *
-getMinChannelCount(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-    return PyInt_FromLong(pd->plugin->getMinChannelCount());
-}
-
-static PyObject *
-getMaxChannelCount(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-    return PyInt_FromLong(pd->plugin->getMaxChannelCount());
-}
-    
-static PyObject *
-unload(PyObject *self, PyObject *)
-{
-    PyPluginObject *pd = getPluginObject(self);
-    if (!pd) return 0;
-
-    delete pd->plugin;
-    pd->plugin = 0; // This is checked by getPluginObject, so we avoid
-                    // blowing up if called repeatedly
-
-    return Py_True;
-}
-
-static PyMemberDef PyPluginObject_members[] =
-{
-    {(char *)"info", T_OBJECT, offsetof(PyPluginObject, info), READONLY,
-     (char *)"info -> A read-only dictionary of plugin metadata."},
-
-    {(char *)"inputDomain", T_INT, offsetof(PyPluginObject, inputDomain), READONLY,
-     (char *)"inputDomain -> The format of input audio required by the plugin, either vampyhost.TimeDomain or vampyhost.FrequencyDomain."},
-
-    {(char *)"parameters", T_OBJECT, offsetof(PyPluginObject, parameters), READONLY,
-     (char *)"parameters -> A list of metadata dictionaries describing the plugin's configurable parameters."},
-
-    {(char *)"programs", T_OBJECT, offsetof(PyPluginObject, programs), READONLY,
-     (char *)"programs -> A list of the programs available for this plugin, if any."},
-    
-    {0, 0}
-};
-
-static PyMethodDef PyPluginObject_methods[] =
-{
-    {"getOutputs", getOutputs, METH_NOARGS,
-     "getOutputs() -> Obtain the output descriptors for all of the plugin's outputs."},
-
-    {"getParameterValue", getParameterValue, METH_VARARGS,
-     "getParameterValue(identifier) -> Return the value of the parameter with the given identifier."},
-
-    {"setParameterValue", setParameterValue, METH_VARARGS,
-     "setParameterValue(identifier, value) -> Set the parameter with the given identifier to the given value."},
-
-    {"setParameterValues", setParameterValues, METH_VARARGS,
-     "setParameterValues(dict) -> Set multiple parameters to values corresponding to the key/value pairs in the dict. Any parameters not mentioned in the dict are unchanged."},
-
-    {"selectProgram", selectProgram, METH_VARARGS,
-     "selectProgram(name) -> Select the processing program with the given name."},
-    
-    {"getPreferredBlockSize", getPreferredBlockSize, METH_VARARGS,
-     "getPreferredBlockSize() -> Return the plugin's preferred processing block size, or 0 if the plugin accepts any block size."},
-
-    {"getPreferredStepSize", getPreferredStepSize, METH_VARARGS,
-     "getPreferredStepSize() -> Return the plugin's preferred processing step size, or 0 if the plugin allows the host to select. If this is 0, the host should normally choose the same step as block size for time-domain plugins, or half the block size for frequency-domain plugins."},
-
-    {"getMinChannelCount", getMinChannelCount, METH_VARARGS,
-     "getMinChannelCount() -> Return the minimum number of channels of audio data the plugin accepts as input."},
-
-    {"getMaxChannelCount", getMaxChannelCount, METH_VARARGS,
-     "getMaxChannelCount() -> Return the maximum number of channels of audio data the plugin accepts as input."},
-    
-    {"initialise", initialise, METH_VARARGS,
-     "initialise(channels, stepSize, blockSize) -> Initialise the plugin for the given number of channels and processing frame sizes. This must be called before process() can be used."},
-
-    {"reset", reset, METH_NOARGS,
-     "reset() -> Reset the plugin after processing, to prepare for another processing run with the same parameters."},
-
-    {"process", process, METH_VARARGS,
-     "process(block, timestamp) -> Provide one processing frame to the plugin, with its timestamp, and obtain any features that were extracted immediately from this frame."},
-
-    {"getRemainingFeatures", getRemainingFeatures, METH_NOARGS,
-     "getRemainingFeatures() -> Obtain any features extracted at the end of processing."},
-
-    {"unload", unload, METH_NOARGS,
-     "unload() -> Dispose of the plugin. You cannot use the plugin object again after calling this. Note that unloading also happens automatically when the plugin object's reference count reaches zero; this function is only necessary if you wish to ensure the native part of the plugin is disposed of before then."},
-    
-    {0, 0}
-};
-
-/* Doc:: 10.3 Type Objects */ /* static */ 
-PyTypeObject Plugin_Type = 
-{
-    PyObject_HEAD_INIT(NULL)
-    0,                                  /*ob_size*/
-    "vampyhost.Plugin",                 /*tp_name*/
-    sizeof(PyPluginObject),             /*tp_basicsize*/
-    0,                                  /*tp_itemsize*/
-    (destructor)PyPluginObject_dealloc, /*tp_dealloc*/
-    0,                                  /*tp_print*/
-    0,                                  /*tp_getattr*/
-    0,                                  /*tp_setattr*/
-    0,                                  /*tp_compare*/
-    0,                                  /*tp_repr*/
-    0,                                  /*tp_as_number*/
-    0,                                  /*tp_as_sequence*/
-    0,                                  /*tp_as_mapping*/
-    0,                                  /*tp_hash*/
-    0,                                  /*tp_call*/
-    0,                                  /*tp_str*/
-    PyObject_GenericGetAttr,            /*tp_getattro*/
-    PyObject_GenericSetAttr,            /*tp_setattro*/
-    0,                                  /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,                 /*tp_flags*/
-    "Plugin object, providing a low-level API for running a Vamp plugin.", /*tp_doc*/
-    0,                                  /*tp_traverse*/
-    0,                                  /*tp_clear*/
-    0,                                  /*tp_richcompare*/
-    0,                                  /*tp_weaklistoffset*/
-    0,                                  /*tp_iter*/
-    0,                                  /*tp_iternext*/
-    PyPluginObject_methods,             /*tp_methods*/ 
-    PyPluginObject_members,             /*tp_members*/
-    0,                                  /*tp_getset*/
-    0,                                  /*tp_base*/
-    0,                                  /*tp_dict*/
-    0,                                  /*tp_descr_get*/
-    0,                                  /*tp_descr_set*/
-    0,                                  /*tp_dictoffset*/
-    0,                                  /*tp_init*/
-    PyType_GenericAlloc,                /*tp_alloc*/
-    0,                                  /*tp_new*/
-    PyObject_Del,                       /*tp_free*/
-    0,                                  /*tp_is_gc*/
-};
-
--- a/PyPluginObject.h	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    VampyHost
-
-    Use Vamp audio analysis plugins in Python
-
-    Gyorgy Fazekas and Chris Cannam
-    Centre for Digital Music, Queen Mary, University of London
-    Copyright 2008-2014 Queen Mary, University of London
-  
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and the authors
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#ifndef PYPLUGINOBJECT_H
-#define PYPLUGINOBJECT_H
-
-#include <Python.h>
-#include <vamp-hostsdk/Plugin.h>
-
-#include <string>
-
-struct PyPluginObject
-{
-    PyObject_HEAD
-    Vamp::Plugin *plugin;
-    bool isInitialised;
-    size_t channels;
-    size_t blockSize;
-    size_t stepSize;
-    PyObject *info;
-    int inputDomain;
-    PyObject *parameters;
-    PyObject *programs;
-};
-
-PyAPI_DATA(PyTypeObject) Plugin_Type;
-#define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type)
-
-PyAPI_FUNC(PyObject *)
-PyPluginObject_From_Plugin(Vamp::Plugin *);
-
-#endif
-
-
--- a/PyRealTime.cpp	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,363 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    VampyHost
-
-    Use Vamp audio analysis plugins in Python
-
-    Gyorgy Fazekas and Chris Cannam
-    Centre for Digital Music, Queen Mary, University of London
-    Copyright 2008-2014 Queen Mary, University of London
-  
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and the authors
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#include "PyRealTime.h"
-
-#include <string>
-
-using namespace std;
-using namespace Vamp;
-
-/* CONSTRUCTOR: New RealTime object from sec and nsec */
-static PyObject*
-RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
-    unsigned int sec = 0;
-    unsigned int nsec = 0;
-    double unary = 0;
-    const char *fmt = NULL;
-
-    if (
-        /// new RealTime from ('format',float) e.g. ('seconds',2.34123)   
-        !PyArg_ParseTuple(args, "|sd:RealTime.new ", 
-                          (const char *) &fmt, 
-                          (double *) &unary)    &&
-
-        /// new RealTime from (sec{int},nsec{int}) e.g. (2,34)
-        !PyArg_ParseTuple(args, "|II:RealTime.new ", 
-                          (unsigned int*) &sec, 
-                          (unsigned int*) &nsec) 
-                
-        ) { 
-        PyErr_SetString(PyExc_TypeError, 
-                        "RealTime initialised with wrong arguments.");
-        return NULL; 
-    }
-
-    // PyErr_Clear();
-
-    // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); 
-    RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0);
-        
-    if (self == NULL) return NULL;
-
-    self->rt = NULL;
-
-    if (sec == 0 && nsec == 0 && fmt == 0) 
-        self->rt = new RealTime();
-    else if (fmt == 0)
-        self->rt = new RealTime(sec,nsec);
-    else { 
-        /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3)
-        if (!string(fmt).compare("float") ||
-            !string(fmt).compare("seconds"))  
-            self->rt = new RealTime( 
-                RealTime::fromSeconds((double) unary)); 
-
-        if (!string(fmt).compare("milliseconds")) {
-            self->rt = new RealTime( 
-                RealTime::fromSeconds((double) unary / 1000.0)); }
-    }
-
-    if (!self->rt) { 
-        PyErr_SetString(PyExc_TypeError, 
-                        "RealTime initialised with wrong arguments.");
-        return NULL; 
-    }
-
-    return (PyObject *) self;
-}
-
-/* DESTRUCTOR: delete type object */
-static void
-RealTimeObject_dealloc(RealTimeObject *self)
-{
-    if (self->rt) delete self->rt;      //delete the C object
-    PyObject_Del(self); //delete the Python object (original)
-    /// this requires PyType_Ready() which fills ob_type
-    // self->ob_type->tp_free((PyObject*)self); 
-}
-
-/* RealTime Object's Methods */ 
-//these are internals not exposed by the module but the object
-
-/* Returns a Tuple containing sec and nsec values */
-static PyObject *
-RealTime_values(RealTimeObject *self)
-{
-    return Py_BuildValue("(ii)",self->rt->sec,self->rt->nsec);
-}
-
-/* Returns a Text representation */
-static PyObject *
-RealTime_toString(RealTimeObject *self, PyObject *args)
-{
-    return Py_BuildValue("s",self->rt->toText().c_str());
-}
-
-/* Frame representation */
-static PyObject *
-RealTime_toFrame(PyObject *self, PyObject *args)
-{
-    unsigned int samplerate;
-        
-    if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", 
-                           (unsigned int *) &samplerate )) {
-        PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required.");
-        return NULL;
-    }
-        
-    return Py_BuildValue("k", 
-                         RealTime::realTime2Frame( 
-                             *(const RealTime*) ((RealTimeObject*)self)->rt, 
-                             (unsigned int) samplerate));
-}
-
-/* Conversion of realtime to a double precision floating point value */
-/* ...in Python called by e.g. float(realtime) */
-static PyObject *
-RealTime_float(PyObject *s)
-{
-    double drt = ((double) ((RealTimeObject*)s)->rt->sec + 
-                  (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
-    return PyFloat_FromDouble(drt);     
-}
-
-
-/* Type object's (RealTime) methods table */
-static PyMethodDef RealTime_methods[] = 
-{
-    {"values",  (PyCFunction)RealTime_values,   METH_NOARGS,
-     PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
-
-    {"toString",        (PyCFunction)RealTime_toString, METH_NOARGS,
-     PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
-
-    {"toFrame", (PyCFunction)RealTime_toFrame,  METH_VARARGS,
-     PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
-
-    {"toFloat", (PyCFunction)RealTime_float,    METH_NOARGS,
-     PyDoc_STR("toFloat() -> Floating point representation.")},
-        
-    {NULL,              NULL}           /* sentinel */
-};
-
-
-/* Methods implementing protocols */ 
-// these functions are called by the interpreter 
-
-/* Object Protocol */
-
-static int
-RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
-{
-
-    if ( !string(name).compare("sec")) { 
-        self->rt->sec= (int) PyInt_AS_LONG(value);
-        return 0;
-    }
-
-    if ( !string(name).compare("nsec")) { 
-        self->rt->nsec= (int) PyInt_AS_LONG(value);
-        return 0;
-    }
-
-    return -1;
-}
-
-static PyObject *
-RealTime_getattr(RealTimeObject *self, char *name)
-{
-
-    if ( !string(name).compare("sec") ) { 
-        return PyInt_FromSsize_t(
-            (Py_ssize_t) self->rt->sec); 
-    } 
-
-    if ( !string(name).compare("nsec") ) { 
-        return PyInt_FromSsize_t(
-            (Py_ssize_t) self->rt->nsec); 
-    } 
-
-    return Py_FindMethod(RealTime_methods, 
-                         (PyObject *)self, name);
-}
-
-/* String representation called by e.g. str(realtime), print realtime*/
-static PyObject *
-RealTime_repr(PyObject *self)
-{
-    return Py_BuildValue("s",
-                         ((RealTimeObject*)self)->rt->toString().c_str());
-}
-
-
-/* Number Protocol */
-/// TODO: implement all methods available in Vamp::RealTime() objects
-
-static PyObject *
-RealTime_add(PyObject *s, PyObject *w)
-{
-    RealTimeObject *result = 
-        PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (result == NULL) return NULL;
-
-    result->rt = new RealTime(
-        *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
-    return (PyObject*)result;
-}
-
-static PyObject *
-RealTime_subtract(PyObject *s, PyObject *w)
-{
-    RealTimeObject *result = 
-        PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (result == NULL) return NULL;
-
-    result->rt = new RealTime(
-        *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
-    return (PyObject*)result;
-}
-
-static PyNumberMethods realtime_as_number = 
-{
-    RealTime_add,                       /*nb_add*/
-    RealTime_subtract,          /*nb_subtract*/
-    0,                                          /*nb_multiply*/
-    0,                                          /*nb_divide*/
-    0,                                          /*nb_remainder*/
-    0,                      /*nb_divmod*/
-    0,                          /*nb_power*/
-    0,                          /*nb_neg*/
-    0,                          /*nb_pos*/
-    0,                          /*(unaryfunc)array_abs,*/
-    0,                          /*nb_nonzero*/
-    0,                          /*nb_invert*/
-    0,                                  /*nb_lshift*/
-    0,                                  /*nb_rshift*/
-    0,                                  /*nb_and*/
-    0,                                  /*nb_xor*/
-    0,                                  /*nb_or*/
-    0,                      /*nb_coerce*/
-    0,                                          /*nb_int*/
-    0,                                  /*nb_long*/
-    (unaryfunc)RealTime_float,/*nb_float*/
-    0,                          /*nb_oct*/
-    0,                          /*nb_hex*/
-};
-
-/* REAL-TIME TYPE OBJECT */
-
-#define RealTime_alloc PyType_GenericAlloc
-#define RealTime_free PyObject_Del
-
-/* Doc:: 10.3 Type Objects */ /* static */ 
-PyTypeObject RealTime_Type = 
-{
-    PyObject_HEAD_INIT(NULL)
-    0,                          /*ob_size*/
-    "vampy.RealTime",           /*tp_name*/
-    sizeof(RealTimeObject),     /*tp_basicsize*/
-    0,                          /*tp_itemsize*/
-    /*          methods         */
-    (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
-    0,                                  /*tp_print*/
-    (getattrfunc)RealTime_getattr, /*tp_getattr*/
-    (setattrfunc)RealTime_setattr, /*tp_setattr*/
-    0,                             /*tp_compare*/
-    RealTime_repr,                 /*tp_repr*/
-    &realtime_as_number,        /*tp_as_number*/
-    0,                          /*tp_as_sequence*/
-    0,                          /*tp_as_mapping*/
-    0,                          /*tp_hash*/
-    0,                      /*tp_call*/
-    0,                      /*tp_str*/
-    0,                      /*tp_getattro*/
-    0,                      /*tp_setattro*/
-    0,                      /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,     /*tp_flags*/
-    "RealTime object, used for Vamp plugin timestamps.",      /*tp_doc*/
-    0,                      /*tp_traverse*/
-    0,                      /*tp_clear*/
-    0,                      /*tp_richcompare*/
-    0,                      /*tp_weaklistoffset*/
-    0,                      /*tp_iter*/
-    0,                      /*tp_iternext*/
-    RealTime_methods,       /*tp_methods*/ //TypeObject Methods
-    0,                      /*tp_members*/
-    0,                      /*tp_getset*/
-    0,                      /*tp_base*/
-    0,                      /*tp_dict*/
-    0,                      /*tp_descr_get*/
-    0,                      /*tp_descr_set*/
-    0,                      /*tp_dictoffset*/
-    0,                      /*tp_init*/
-    RealTime_alloc,         /*tp_alloc*/
-    RealTime_new,           /*tp_new*/
-    RealTime_free,          /*tp_free*/
-    0,                      /*tp_is_gc*/
-};
-
-
-
-/* PyRealTime C++ API */
-
-/*PyRealTime from RealTime*/
-PyObject* 
-PyRealTime_FromRealTime(const Vamp::RealTime& rt) {
-
-    RealTimeObject *self =
-        PyObject_New(RealTimeObject, &RealTime_Type); 
-    if (self == NULL) return NULL;
-
-    self->rt = new RealTime(rt);
-    return (PyObject*) self;
-}
-
-/*RealTime* from PyRealTime*/
-const Vamp::RealTime*
-PyRealTime_AsRealTime (PyObject *self) { 
-
-    RealTimeObject *s = (RealTimeObject*) self; 
-
-    if (!PyRealTime_Check(s)) {
-        PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
-        cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
-        return NULL; }
-    return s->rt; 
-};
-
--- a/PyRealTime.h	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    VampyHost
-
-    Use Vamp audio analysis plugins in Python
-
-    Gyorgy Fazekas and Chris Cannam
-    Centre for Digital Music, Queen Mary, University of London
-    Copyright 2008-2014 Queen Mary, University of London
-  
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and the authors
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#ifndef PYREALTIME_H
-#define PYREALTIME_H
-
-#include <Python.h>
-#include <vamp-hostsdk/RealTime.h>
-
-typedef struct {
-    PyObject_HEAD
-    Vamp::RealTime *rt;
-} RealTimeObject; 
-
-PyAPI_DATA(PyTypeObject) RealTime_Type;
-
-#define PyRealTime_Check(v) PyObject_TypeCheck(v, &RealTime_Type)
-#define PyRealTime_AS_REALTIME(v) ((const RealTimeObject* const) (v))->rt
-
-PyAPI_FUNC(PyObject *) 
-PyRealTime_FromRealTime(const Vamp::RealTime&);
-
-PyAPI_FUNC(const Vamp::RealTime*) 
-PyRealTime_AsRealTime (PyObject *self);
-
-#endif
--- a/VectorConversion.cpp	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-  VampyHost
-
-  Use Vamp audio analysis plugins in Python
-
-  Gyorgy Fazekas and Chris Cannam
-  Centre for Digital Music, Queen Mary, University of London
-  Copyright 2008-2014 Queen Mary, University of London
-  
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation
-  files (the "Software"), to deal in the Software without
-  restriction, including without limitation the rights to use, copy,
-  modify, merge, publish, distribute, sublicense, and/or sell copies
-  of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-  Except as contained in this notice, the names of the Centre for
-  Digital Music; Queen Mary, University of London; and the authors
-  shall not be used in advertising or otherwise to promote the sale,
-  use or other dealings in this Software without prior written
-  authorization.
-*/
-
-#include <Python.h>
-
-#include "FloatConversion.h"
-#include "VectorConversion.h"
-
-#include <math.h>
-#include <float.h>
-
-using namespace std;
-
-/*  Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
-    (EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
-
-VectorConversion::VectorConversion() : 
-    m_error(false),
-    error(m_error) // const public reference for easy access
-{
-}
-
-VectorConversion::~VectorConversion()
-{
-}
-
-/// floating point numbers (TODO: check numpy.float128)
-float 
-VectorConversion::PyValue_To_Float(PyObject* pyValue) const
-{
-    if (FloatConversion::check(pyValue)) {
-        return FloatConversion::convert(pyValue);
-    }
-
-    setValueError("Conversion error: object" + PyValue_Get_TypeName(pyValue) +" is not float, int, or long.");
-    return 0.0;
-}
-
-vector<float> 
-VectorConversion::PyValue_To_FloatVector (PyObject *pyValue) const 
-{
-    /// numpy array
-    if (PyArray_CheckExact(pyValue)) 
-        return PyArray_To_FloatVector(pyValue);
-
-    /// python list of floats (backward compatible)
-    if (PyList_Check(pyValue)) {
-        return PyList_To_FloatVector(pyValue);
-    }
-
-    string msg = "Value is not list or array of floats";
-    setValueError(msg);
-#ifdef _DEBUG
-    cerr << "VectorConversion::PyValue_To_FloatVector failed. " << msg << endl;
-#endif
-    return vector<float>();
-}
-
-vector<float> 
-VectorConversion::PyList_To_FloatVector (PyObject *inputList) const 
-{
-    vector<float> v;
-	
-    if (!PyList_Check(inputList)) {
-        setValueError("Value is not a list");
-        return v;
-    } 
-
-    PyObject **pyObjectArray = PySequence_Fast_ITEMS(inputList);
-    int n = PyList_GET_SIZE(inputList);
-
-    for (int i = 0; i < n; ++i) {
-        v.push_back(PyValue_To_Float(pyObjectArray[i]));
-    }
-    
-    return v;
-}
-
-vector<float> 
-VectorConversion::PyArray_To_FloatVector (PyObject *pyValue) const 
-{
-    vector<float> v;
-	
-    if (!PyArray_Check(pyValue)) {
-        setValueError("Value is not an array");
-        return v;
-    } 
-
-    PyArrayObject* pyArray = (PyArrayObject*) pyValue;
-    PyArray_Descr* descr = PyArray_DESCR(pyArray);
-	
-    if (PyArray_DATA(pyArray) == 0 || descr == 0) {
-        string msg = "NumPy array with NULL data or descriptor pointer encountered.";
-        setValueError(msg);
-        return v;
-    }
-
-    if (PyArray_NDIM(pyArray) != 1) {
-        string msg = "NumPy array must be a one-dimensional vector.";
-        setValueError(msg);
-        return v;
-    }
-
-    /// check strides (useful if array is not continuous)
-    size_t strides =  *((size_t*) PyArray_STRIDES(pyArray));
-    
-    /// convert the array
-    switch (descr->type_num) {
-        
-    case NPY_FLOAT : // dtype='float32'
-        return PyArray_Convert<float,float>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
-    case NPY_DOUBLE : // dtype='float64'
-        return PyArray_Convert<float,double>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
-    case NPY_INT : // dtype='int'
-        return PyArray_Convert<float,int>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
-    case NPY_LONG : // dtype='long'
-        return PyArray_Convert<float,long>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
-    default :
-        string msg = "Unsupported value type in NumPy array object.";
-        setValueError(msg);
-#ifdef _DEBUG
-        cerr << "VectorConversion::PyArray_To_FloatVector failed. Error: " << msg << endl;
-#endif			
-        return v;
-    }
-}
-
-vector<vector<float> >
-VectorConversion::Py2DArray_To_FloatVector (PyObject *pyValue) const 
-{
-    vector<vector<float> > v;
-	
-    if (!PyArray_Check(pyValue)) {
-        setValueError("Value is not an array");
-        return v;
-    } 
-
-    PyArrayObject* pyArray = (PyArrayObject*) pyValue;
-    PyArray_Descr* descr = PyArray_DESCR(pyArray);
-	
-    if (PyArray_DATA(pyArray) == 0 || descr == 0) {
-        string msg = "NumPy array with NULL data or descriptor pointer encountered.";
-        setValueError(msg);
-        return v;
-    }
-
-    if (PyArray_NDIM(pyArray) != 2) {
-        string msg = "NumPy array must be a two-dimensional matrix.";
-        setValueError(msg);
-        return v;
-    }
-
-    /// check strides (useful if array is not continuous)
-    size_t *strideptr =  (size_t*) PyArray_STRIDES(pyArray);
-    
-    /// convert the array
-    for (int i = 0; i < PyArray_DIMS(pyArray)[0]; ++i) {
-
-        vector<float> vv;
-        
-        switch (descr->type_num) {
-        
-        case NPY_FLOAT : // dtype='float32'
-            vv = PyArray_Convert<float,float>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
-            break;
-        case NPY_DOUBLE : // dtype='float64'
-            vv = PyArray_Convert<float,double>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
-            break;
-        case NPY_INT : // dtype='int'
-            vv = PyArray_Convert<float,int>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
-            break;
-        case NPY_LONG : // dtype='long'
-            vv = PyArray_Convert<float,long>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
-            break;
-        default :
-            string msg = "Unsupported value type in NumPy array object.";
-            cerr << "VectorConversion::PyArray_To_FloatVector failed (value type = " << descr->type_num << "). Error: " << msg << endl;
-            setValueError(msg);
-            return v;
-        }
-
-        v.push_back(vv);
-    }
-
-    return v;
-}
-
-PyObject *
-VectorConversion::PyArray_From_FloatVector(const vector<float> &v) const
-{
-    npy_intp ndims[1];
-    ndims[0] = (int)v.size();
-    PyObject *arr = PyArray_SimpleNew(1, ndims, NPY_FLOAT);
-    float *data = (float *)PyArray_DATA((PyArrayObject *)arr);
-    for (int i = 0; i < ndims[0]; ++i) {
-        data[i] = v[i];
-    }
-    return arr;
-}
-
-PyObject *
-VectorConversion::PyValue_From_StringVector(const vector<string> &v) const
-{
-    PyObject *pyList = PyList_New(v.size());
-    for (size_t i = 0; i < v.size(); ++i) {
-        PyObject *pyStr = PyString_FromString(v[i].c_str());
-        PyList_SET_ITEM(pyList, i, pyStr);
-    }
-    return pyList;
-}
-
-
-/* Error handling */
-
-void
-VectorConversion::setValueError (string message) const
-{
-    m_error = true;
-    m_errorQueue.push(ValueError(message));
-}
-
-/// return a reference to the last error or creates a new one.
-ValueError&
-VectorConversion::lastError() const 
-{
-    m_error = false;
-    if (!m_errorQueue.empty()) return m_errorQueue.back();
-    else {
-        m_errorQueue.push(ValueError("Type conversion error."));
-        return m_errorQueue.back();
-    }
-}
-
-/// helper function to iterate over the error message queue:
-/// pops the oldest item
-ValueError 
-VectorConversion::getError() const
-{
-    if (!m_errorQueue.empty()) {
-        ValueError e = m_errorQueue.front();
-        m_errorQueue.pop();
-        if (m_errorQueue.empty()) m_error = false;
-        return e;
-    }
-    else {
-        m_error = false;
-        return ValueError();
-    }
-}
-
-/* Utilities */
-
-/// get the type name of an object
-string
-VectorConversion::PyValue_Get_TypeName(PyObject* pyValue) const
-{
-    PyObject *pyType = PyObject_Type(pyValue);
-    if (!pyType) 
-    {
-        cerr << "Warning: Object type name could not be found." << endl;
-        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
-        return string ("< unknown type >");
-    }
-    PyObject *pyString = PyObject_Str(pyType);
-    if (!pyString)
-    {
-        cerr << "Warning: Object type name could not be found." << endl;
-        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
-        Py_CLEAR(pyType);
-        return string ("< unknown type >");
-    }
-    char *cstr = PyString_AS_STRING(pyString);
-    if (!cstr)
-    {
-        cerr << "Warning: Object type name could not be found." << endl;
-        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
-        Py_DECREF(pyType);
-        Py_CLEAR(pyString);
-        return string("< unknown type >");
-    }
-    Py_DECREF(pyType);
-    Py_DECREF(pyString);
-    return string(cstr);
-}
--- a/VectorConversion.h	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-  VampyHost
-
-  Use Vamp audio analysis plugins in Python
-
-  Gyorgy Fazekas and Chris Cannam
-  Centre for Digital Music, Queen Mary, University of London
-  Copyright 2008-2014 Queen Mary, University of London
-  
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation
-  files (the "Software"), to deal in the Software without
-  restriction, including without limitation the rights to use, copy,
-  modify, merge, publish, distribute, sublicense, and/or sell copies
-  of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-  Except as contained in this notice, the names of the Centre for
-  Digital Music; Queen Mary, University of London; and the authors
-  shall not be used in advertising or otherwise to promote the sale,
-  use or other dealings in this Software without prior written
-  authorization.
-*/
-
-/*
-  VectorConversion: A handful of type safe conversion utilities
-  between Python types and C++ vectors.
-*/
-
-#ifndef VAMPYHOST_VECTOR_CONVERSION_H
-#define VAMPYHOST_VECTOR_CONVERSION_H
-
-#include <Python.h>
-
-// NumPy is required here
-#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
-#define NO_IMPORT_ARRAY
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#include "numpy/arrayobject.h"
-
-#include <vector>
-#include <queue>
-#include <string>
-#include <sstream>
-#include <iostream>
-	
-// Data
-class ValueError
-{
-public:
-    ValueError() {}
-    ValueError(std::string m) : message(m) {}
-    std::string location;
-    std::string message;
-    std::string str() const { 
-        return (location.empty()) ? message : message + "\nLocation: " + location;}
-    template<typename V> ValueError &operator<< (const V& v)
-    {
-        std::ostringstream ss;
-        ss << v;
-        location += ss.str();
-        return *this;
-    }
-};
-
-class VectorConversion
-{
-public:
-    VectorConversion();
-    ~VectorConversion();
-
-    ValueError getError() const;
-
-    std::vector<float> PyValue_To_FloatVector (PyObject*) const;
-    std::vector<float> PyArray_To_FloatVector (PyObject *) const;
-    std::vector<float> PyList_To_FloatVector (PyObject*) const;
-    std::vector<std::vector<float> > Py2DArray_To_FloatVector (PyObject *) const;
-    
-    PyObject *PyValue_From_StringVector(const std::vector<std::string> &) const;
-    PyObject *PyArray_From_FloatVector(const std::vector<float> &) const;
-
-private:
-    std::string PyValue_Get_TypeName(PyObject*) const;
-    float PyValue_To_Float(PyObject*) const;
-
-    /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
-    template<typename RET, typename DTYPE>
-    std::vector<RET> PyArray_Convert(void* raw_data_ptr,
-                                     int length,
-                                     size_t strides) const {
-
-        std::vector<RET> v(length);
-		
-        /// check if the array is continuous, if not use strides info
-        if (sizeof(DTYPE) != strides) {
-#ifdef _DEBUG_VALUES
-            cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
-#endif
-            char* data = (char*) raw_data_ptr;
-            for (int i = 0; i < length; ++i){
-                v[i] = (RET)(*((DTYPE*)data));
-                data += strides;
-            }
-            return v;
-        }
-
-        DTYPE* data = (DTYPE*) raw_data_ptr;
-        for (int i = 0; i < length; ++i){
-            v[i] = (RET)data[i];
-        }
-
-        return v;
-    }
-
-private:
-    mutable bool m_error;
-    mutable std::queue<ValueError> m_errorQueue;
-	
-    void setValueError(std::string) const;
-    ValueError& lastError() const;
-    
-public:
-    const bool& error;
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/FloatConversion.h	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,76 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+  VampyHost
+
+  Use Vamp audio analysis plugins in Python
+
+  Gyorgy Fazekas and Chris Cannam
+  Centre for Digital Music, Queen Mary, University of London
+  Copyright 2008-2014 Queen Mary, University of London
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy,
+  modify, merge, publish, distribute, sublicense, and/or sell copies
+  of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+  Except as contained in this notice, the names of the Centre for
+  Digital Music; Queen Mary, University of London; and the authors
+  shall not be used in advertising or otherwise to promote the sale,
+  use or other dealings in this Software without prior written
+  authorization.
+*/
+
+#ifndef VAMPYHOST_FLOAT_CONVERSION_H
+#define VAMPYHOST_FLOAT_CONVERSION_H
+
+class FloatConversion
+{
+public:
+    static bool check(PyObject *pyValue) {
+	if (pyValue && PyFloat_Check(pyValue)) {
+	    return true;
+	}
+	if (pyValue && PyLong_Check(pyValue)) {
+	    return true;
+	}
+	if (pyValue && PyInt_Check(pyValue)) {
+	    return true;
+	}
+	return false;
+    }
+	
+    static float convert(PyObject* pyValue) {
+	
+	if (pyValue && PyFloat_Check(pyValue)) {
+	    return (float) PyFloat_AS_DOUBLE(pyValue);
+	}
+
+	if (pyValue && PyLong_Check(pyValue)) {
+	    return (float) PyLong_AsDouble(pyValue);
+	}
+
+	if (pyValue && PyInt_Check(pyValue)) {
+	    return (float) PyInt_AsLong(pyValue);
+	}
+
+	return 0.0;
+    }
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/PyPluginObject.cpp	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,725 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    VampyHost
+
+    Use Vamp audio analysis plugins in Python
+
+    Gyorgy Fazekas and Chris Cannam
+    Centre for Digital Music, Queen Mary, University of London
+    Copyright 2008-2014 Queen Mary, University of London
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and the authors
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PyPluginObject.h"
+
+// define a unique API pointer 
+#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#define NO_IMPORT_ARRAY
+#include "numpy/arrayobject.h"
+
+#include "structmember.h"
+
+#include "FloatConversion.h"
+#include "VectorConversion.h"
+#include "PyRealTime.h"
+
+#include <string>
+#include <vector>
+#include <cstddef>
+#include <set>
+
+using namespace std;
+using namespace Vamp;
+
+static
+PyPluginObject *
+getPluginObject(PyObject *pyPluginHandle)
+{
+    PyPluginObject *pd = 0;
+    if (PyPlugin_Check(pyPluginHandle)) {
+        pd = (PyPluginObject *)pyPluginHandle;
+    }
+    if (!pd || !pd->plugin) {
+        PyErr_SetString(PyExc_AttributeError,
+                        "Invalid or already deleted plugin handle.");
+        return 0;
+    } else {
+        return pd;
+    }
+}
+
+static
+PyObject *
+pystr(const string &s)
+{
+    return PyString_FromString(s.c_str());
+}
+
+PyObject *
+PyPluginObject_From_Plugin(Plugin *plugin)
+{
+    PyPluginObject *pd = 
+        (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0);
+    pd->plugin = plugin;
+    pd->isInitialised = false;
+    pd->channels = 0;
+    pd->blockSize = 0;
+    pd->stepSize = 0;
+
+    PyObject *infodict = PyDict_New();
+    PyDict_SetItemString
+        (infodict, "apiVersion", PyInt_FromLong(plugin->getVampApiVersion()));
+    PyDict_SetItemString
+        (infodict, "pluginVersion", PyInt_FromLong(plugin->getPluginVersion()));
+    PyDict_SetItemString
+        (infodict, "identifier", pystr(plugin->getIdentifier()));
+    PyDict_SetItemString
+        (infodict, "name", pystr(plugin->getName()));
+    PyDict_SetItemString
+        (infodict, "description", pystr(plugin->getDescription()));
+    PyDict_SetItemString
+        (infodict, "maker", pystr(plugin->getMaker()));
+    PyDict_SetItemString
+        (infodict, "copyright", pystr(plugin->getCopyright()));
+    pd->info = infodict;
+
+    pd->inputDomain = plugin->getInputDomain();
+
+    VectorConversion conv;
+
+    Plugin::ParameterList pl = plugin->getParameterDescriptors();
+    PyObject *params = PyList_New(pl.size());
+    
+    for (int i = 0; i < (int)pl.size(); ++i) {
+        PyObject *paramdict = PyDict_New();
+        PyDict_SetItemString
+            (paramdict, "identifier", pystr(pl[i].identifier));
+        PyDict_SetItemString
+            (paramdict, "name", pystr(pl[i].name));
+        PyDict_SetItemString
+            (paramdict, "description", pystr(pl[i].description));
+        PyDict_SetItemString
+            (paramdict, "unit", pystr(pl[i].unit));
+        PyDict_SetItemString
+            (paramdict, "minValue", PyFloat_FromDouble(pl[i].minValue));
+        PyDict_SetItemString
+            (paramdict, "maxValue", PyFloat_FromDouble(pl[i].maxValue));
+        PyDict_SetItemString
+            (paramdict, "defaultValue", PyFloat_FromDouble(pl[i].defaultValue));
+        if (pl[i].isQuantized) {
+            PyDict_SetItemString
+                (paramdict, "isQuantized", Py_True);
+            PyDict_SetItemString
+                (paramdict, "quantizeStep", PyFloat_FromDouble(pl[i].quantizeStep));
+            if (!pl[i].valueNames.empty()) {
+                PyDict_SetItemString
+                    (paramdict, "valueNames", conv.PyValue_From_StringVector(pl[i].valueNames));
+            }
+        } else {
+            PyDict_SetItemString
+                (paramdict, "isQuantized", Py_False);
+        }
+        
+        PyList_SET_ITEM(params, i, paramdict);
+    }
+
+    pd->parameters = params;
+
+    Plugin::ProgramList prl = plugin->getPrograms();
+    PyObject *progs = PyList_New(prl.size());
+
+    for (int i = 0; i < (int)prl.size(); ++i) {
+        PyList_SET_ITEM(progs, i, pystr(prl[i]));
+    }
+
+    pd->programs = progs;
+    
+    return (PyObject *)pd;
+}
+
+static void
+PyPluginObject_dealloc(PyPluginObject *self)
+{
+    delete self->plugin;
+    PyObject_Del(self);
+}
+
+static PyObject *
+getOutputs(PyObject *self, PyObject *args)
+{ 
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    Plugin::OutputList ol = pd->plugin->getOutputDescriptors();
+    PyObject *outputs = PyList_New(ol.size());
+    
+    for (int i = 0; i < (int)ol.size(); ++i) {
+        PyObject *outdict = PyDict_New();
+        PyDict_SetItemString
+            (outdict, "identifier", pystr(ol[i].identifier));
+        PyDict_SetItemString
+            (outdict, "name", pystr(ol[i].name));
+        PyDict_SetItemString
+            (outdict, "description", pystr(ol[i].description));
+        PyDict_SetItemString
+            (outdict, "binCount", PyInt_FromLong(ol[i].binCount));
+        if (ol[i].binCount > 0) {
+            if (ol[i].hasKnownExtents) {
+                PyDict_SetItemString
+                    (outdict, "hasKnownExtents", Py_True);
+                PyDict_SetItemString
+                    (outdict, "minValue", PyFloat_FromDouble(ol[i].minValue));
+                PyDict_SetItemString
+                    (outdict, "maxValue", PyFloat_FromDouble(ol[i].maxValue));
+            } else {
+                PyDict_SetItemString
+                    (outdict, "hasKnownExtents", Py_False);
+            }
+            if (ol[i].isQuantized) {
+                PyDict_SetItemString
+                    (outdict, "isQuantized", Py_True);
+                PyDict_SetItemString
+                    (outdict, "quantizeStep", PyFloat_FromDouble(ol[i].quantizeStep));
+            } else {
+                PyDict_SetItemString
+                    (outdict, "isQuantized", Py_False);
+            }
+        }
+        PyDict_SetItemString
+            (outdict, "sampleType", PyInt_FromLong((int)ol[i].sampleType));
+        PyDict_SetItemString
+            (outdict, "sampleRate", PyFloat_FromDouble(ol[i].sampleRate));
+        PyDict_SetItemString
+            (outdict, "hasDuration", ol[i].hasDuration ? Py_True : Py_False);
+        
+        PyList_SET_ITEM(outputs, i, outdict);
+    }
+
+    return outputs;
+}
+
+static PyObject *
+initialise(PyObject *self, PyObject *args)
+{
+    size_t channels, blockSize, stepSize;
+
+    if (!PyArg_ParseTuple (args, "nnn",
+                           (size_t) &channels,
+                           (size_t) &stepSize,
+                           (size_t) &blockSize)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "initialise() takes channel count, step size, and block size arguments");
+        return 0;
+    }
+
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    pd->channels = channels;
+    pd->stepSize = stepSize;
+    pd->blockSize = blockSize;
+
+    if (!pd->plugin->initialise(channels, stepSize, blockSize)) {
+        cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << endl;
+        PyErr_SetString(PyExc_TypeError,
+                        "Plugin initialization failed");
+        return 0;
+    }
+
+    pd->isInitialised = true;
+
+    return Py_True;
+}
+
+static PyObject *
+reset(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    if (!pd->isInitialised) {
+        PyErr_SetString(PyExc_StandardError,
+                        "Plugin has not been initialised");
+        return 0;
+    }
+        
+    pd->plugin->reset();
+    return Py_True;
+}
+
+static bool
+hasParameter(PyPluginObject *pd, string id)
+{
+    PluginBase::ParameterList pl = pd->plugin->getParameterDescriptors();
+    for (int i = 0; i < (int)pl.size(); ++i) {
+        if (pl[i].identifier == id) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static PyObject *
+getParameterValue(PyObject *self, PyObject *args)
+{
+    PyObject *pyParam;
+
+    if (!PyArg_ParseTuple(args, "S", &pyParam)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "getParameterValue() takes parameter id (string) argument");
+        return 0; }
+
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    string param = PyString_AS_STRING(pyParam);
+    
+    if (!hasParameter(pd, param)) {
+        PyErr_SetString(PyExc_StandardError,
+                        (string("Unknown parameter id \"") + param + "\"").c_str());
+        return 0;
+    }
+    
+    float value = pd->plugin->getParameter(param);
+    return PyFloat_FromDouble(double(value));
+}
+
+static PyObject *
+setParameterValue(PyObject *self, PyObject *args)
+{
+    PyObject *pyParam;
+    float value;
+
+    if (!PyArg_ParseTuple(args, "Sf", &pyParam, &value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "setParameterValue() takes parameter id (string), and value (float) arguments");
+        return 0; }
+
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    string param = PyString_AS_STRING(pyParam);
+    
+    if (!hasParameter(pd, param)) {
+        PyErr_SetString(PyExc_StandardError,
+                        (string("Unknown parameter id \"") + param + "\"").c_str());
+        return 0;
+    }
+
+    pd->plugin->setParameter(param, value);
+    return Py_True;
+}
+
+static PyObject *
+setParameterValues(PyObject *self, PyObject *args)
+{
+    PyObject *dict;
+
+    if (!PyArg_ParseTuple(args, "O", &dict)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "setParameterValues() takes dict argument");
+        return 0; }
+
+    if (!PyDict_Check(dict)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "setParameterValues() takes dict argument");
+        return 0; }
+    
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    PluginBase::ParameterList pl = pd->plugin->getParameterDescriptors();
+    set<string> paramIds;
+    for (int i = 0; i < (int)pl.size(); ++i) {
+        paramIds.insert(pl[i].identifier);
+    }
+
+    Py_ssize_t pos = 0;
+    PyObject *key, *value;
+    while (PyDict_Next(dict, &pos, &key, &value)) {
+        if (!key || !PyString_CheckExact(key)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "Parameter dict keys must all have string type");
+            return 0;
+        }
+        if (!value || !FloatConversion::check(value)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "Parameter dict values must be convertible to float");
+            return 0;
+        }
+        string param = PyString_AS_STRING(key);
+        if (paramIds.find(param) == paramIds.end()) {
+            PyErr_SetString(PyExc_StandardError,
+                            (string("Unknown parameter id \"") + param + "\"").c_str());
+            return 0;
+        }
+        pd->plugin->setParameter(param, FloatConversion::convert(value));
+    }
+    
+    return Py_True;
+}
+
+static PyObject *
+selectProgram(PyObject *self, PyObject *args)
+{
+    PyObject *pyParam;
+
+    if (!PyArg_ParseTuple(args, "S", &pyParam)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "selectProgram() takes parameter id (string) argument");
+        return 0; }
+
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    pd->plugin->selectProgram(PyString_AS_STRING(pyParam));
+    return Py_True;
+}
+
+static
+PyObject *
+convertFeatureSet(const Plugin::FeatureSet &fs)
+{
+    VectorConversion conv;
+    
+    PyObject *pyFs = PyDict_New();
+
+    for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
+         fsi != fs.end(); ++fsi) {
+
+        int fno = fsi->first;
+        const Plugin::FeatureList &fl = fsi->second;
+
+        if (!fl.empty()) {
+
+            PyObject *pyFl = PyList_New(fl.size());
+
+            for (int fli = 0; fli < (int)fl.size(); ++fli) {
+
+                const Plugin::Feature &f = fl[fli];
+                PyObject *pyF = PyDict_New();
+
+                if (f.hasTimestamp) {
+                    PyDict_SetItemString
+                        (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp));
+                }
+                if (f.hasDuration) {
+                    PyDict_SetItemString
+                        (pyF, "duration", PyRealTime_FromRealTime(f.duration));
+                }
+
+                PyDict_SetItemString
+                    (pyF, "label", pystr(f.label));
+
+                if (!f.values.empty()) {
+                    PyDict_SetItemString
+                        (pyF, "values", conv.PyArray_From_FloatVector(f.values));
+                }
+
+                PyList_SET_ITEM(pyFl, fli, pyF);
+            }
+
+            PyObject *pyN = PyInt_FromLong(fno);
+            PyDict_SetItem(pyFs, pyN, pyFl);
+        }
+    }
+    
+    return pyFs;
+}
+
+static vector<vector<float> >
+convertPluginInput(PyObject *pyBuffer, int channels, int blockSize)
+{
+    vector<vector<float> > data;
+
+    VectorConversion conv;
+
+    if (PyArray_CheckExact(pyBuffer)) {
+
+        data = conv.Py2DArray_To_FloatVector(pyBuffer);
+
+        if (conv.error) {
+            PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
+            return data;
+        }
+
+        if ((int)data.size() != channels) {
+//            cerr << "Wrong number of channels: got " << data.size() << ", expected " << channels << endl;
+            PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
+            return vector<vector<float> >();
+        }
+        
+    } else {
+        
+        if (!PyList_Check(pyBuffer)) {
+            PyErr_SetString(PyExc_TypeError, "List of NumPy arrays or lists of numbers required for process input");
+            return data;
+        }
+        
+        if (PyList_GET_SIZE(pyBuffer) != channels) {
+//            cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
+            PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
+            return data;
+        }
+
+        for (int c = 0; c < channels; ++c) {
+            PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
+            data.push_back(conv.PyValue_To_FloatVector(cbuf));
+            if (conv.error) {
+                PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
+                return vector<vector<float> >();
+            }
+        }
+    }
+    
+    for (int c = 0; c < channels; ++c) {
+        if ((int)data[c].size() != blockSize) {
+//            cerr << "Wrong number of samples on channel " << c << ": expected " << blockSize << " (plugin's block size), got " << data[c].size() << endl;
+            PyErr_SetString(PyExc_TypeError, "Wrong number of samples for process block");
+            return vector<vector<float> >();
+        }
+    }
+    
+    return data;
+}
+
+static PyObject *
+processBlock(PyObject *self, PyObject *args)
+{
+    PyObject *pyBuffer;
+    PyObject *pyRealTime;
+
+    if (!PyArg_ParseTuple(args, "OO",
+                          &pyBuffer,                    // Audio data
+                          &pyRealTime)) {               // TimeStamp
+        PyErr_SetString(PyExc_TypeError,
+                        "processBlock() takes buffer (2D array or list of arrays, one row per channel) and timestamp (RealTime) arguments");
+        return 0; }
+
+    if (!PyRealTime_Check(pyRealTime)) {
+        PyErr_SetString(PyExc_TypeError, "Valid timestamp required.");
+        return 0; }
+
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    if (!pd->isInitialised) {
+        PyErr_SetString(PyExc_StandardError,
+                        "Plugin has not been initialised.");
+        return 0;
+    }
+
+    int channels = pd->channels;
+    vector<vector<float> > data =
+        convertPluginInput(pyBuffer, channels, pd->blockSize);
+    if (data.empty()) return 0;
+
+    float **inbuf = new float *[channels];
+    for (int c = 0; c < channels; ++c) {
+        inbuf[c] = &data[c][0];
+    }
+    RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
+    Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
+    delete[] inbuf;
+
+    return convertFeatureSet(fs);
+}
+
+static PyObject *
+getRemainingFeatures(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    if (!pd->isInitialised) {
+        PyErr_SetString(PyExc_StandardError,
+                        "Plugin has not been initialised.");
+        return 0;
+    }
+
+    Plugin::FeatureSet fs = pd->plugin->getRemainingFeatures();
+
+    return convertFeatureSet(fs);
+}
+
+static PyObject *
+getPreferredBlockSize(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+    return PyInt_FromLong(pd->plugin->getPreferredBlockSize());
+}
+
+static PyObject *
+getPreferredStepSize(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+    return PyInt_FromLong(pd->plugin->getPreferredStepSize());
+}
+
+static PyObject *
+getMinChannelCount(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+    return PyInt_FromLong(pd->plugin->getMinChannelCount());
+}
+
+static PyObject *
+getMaxChannelCount(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+    return PyInt_FromLong(pd->plugin->getMaxChannelCount());
+}
+    
+static PyObject *
+unload(PyObject *self, PyObject *)
+{
+    PyPluginObject *pd = getPluginObject(self);
+    if (!pd) return 0;
+
+    delete pd->plugin;
+    pd->plugin = 0; // This is checked by getPluginObject, so we avoid
+                    // blowing up if called repeatedly
+
+    return Py_True;
+}
+
+static PyMemberDef PyPluginObject_members[] =
+{
+    {(char *)"info", T_OBJECT, offsetof(PyPluginObject, info), READONLY,
+     (char *)"info -> A read-only dictionary of plugin metadata."},
+
+    {(char *)"inputDomain", T_INT, offsetof(PyPluginObject, inputDomain), READONLY,
+     (char *)"inputDomain -> The format of input audio required by the plugin, either vampyhost.TimeDomain or vampyhost.FrequencyDomain."},
+
+    {(char *)"parameters", T_OBJECT, offsetof(PyPluginObject, parameters), READONLY,
+     (char *)"parameters -> A list of metadata dictionaries describing the plugin's configurable parameters."},
+
+    {(char *)"programs", T_OBJECT, offsetof(PyPluginObject, programs), READONLY,
+     (char *)"programs -> A list of the programs available for this plugin, if any."},
+    
+    {0, 0}
+};
+
+static PyMethodDef PyPluginObject_methods[] =
+{
+    {"getOutputs", getOutputs, METH_NOARGS,
+     "getOutputs() -> Obtain the output descriptors for all of the plugin's outputs."},
+
+    {"getParameterValue", getParameterValue, METH_VARARGS,
+     "getParameterValue(identifier) -> Return the value of the parameter with the given identifier."},
+
+    {"setParameterValue", setParameterValue, METH_VARARGS,
+     "setParameterValue(identifier, value) -> Set the parameter with the given identifier to the given value."},
+
+    {"setParameterValues", setParameterValues, METH_VARARGS,
+     "setParameterValues(dict) -> Set multiple parameters to values corresponding to the key/value pairs in the dict. Any parameters not mentioned in the dict are unchanged."},
+
+    {"selectProgram", selectProgram, METH_VARARGS,
+     "selectProgram(name) -> Select the processing program with the given name."},
+    
+    {"getPreferredBlockSize", getPreferredBlockSize, METH_VARARGS,
+     "getPreferredBlockSize() -> Return the plugin's preferred processing block size, or 0 if the plugin accepts any block size."},
+
+    {"getPreferredStepSize", getPreferredStepSize, METH_VARARGS,
+     "getPreferredStepSize() -> Return the plugin's preferred processing step size, or 0 if the plugin allows the host to select. If this is 0, the host should normally choose the same step as block size for time-domain plugins, or half the block size for frequency-domain plugins."},
+
+    {"getMinChannelCount", getMinChannelCount, METH_VARARGS,
+     "getMinChannelCount() -> Return the minimum number of channels of audio data the plugin accepts as input."},
+
+    {"getMaxChannelCount", getMaxChannelCount, METH_VARARGS,
+     "getMaxChannelCount() -> Return the maximum number of channels of audio data the plugin accepts as input."},
+    
+    {"initialise", initialise, METH_VARARGS,
+     "initialise(channels, stepSize, blockSize) -> Initialise the plugin for the given number of channels and processing frame sizes. This must be called before processBlock() can be used."},
+
+    {"reset", reset, METH_NOARGS,
+     "reset() -> Reset the plugin after processing, to prepare for another processing run with the same parameters."},
+
+    {"processBlock", processBlock, METH_VARARGS,
+     "processBlock(block, timestamp) -> Provide one processing frame to the plugin, with its timestamp, and obtain any features that were extracted immediately from this frame."},
+
+    {"getRemainingFeatures", getRemainingFeatures, METH_NOARGS,
+     "getRemainingFeatures() -> Obtain any features extracted at the end of processing."},
+
+    {"unload", unload, METH_NOARGS,
+     "unload() -> Dispose of the plugin. You cannot use the plugin object again after calling this. Note that unloading also happens automatically when the plugin object's reference count reaches zero; this function is only necessary if you wish to ensure the native part of the plugin is disposed of before then."},
+    
+    {0, 0}
+};
+
+/* Doc:: 10.3 Type Objects */ /* static */ 
+PyTypeObject Plugin_Type = 
+{
+    PyObject_HEAD_INIT(NULL)
+    0,                                  /*ob_size*/
+    "vampyhost.Plugin",                 /*tp_name*/
+    sizeof(PyPluginObject),             /*tp_basicsize*/
+    0,                                  /*tp_itemsize*/
+    (destructor)PyPluginObject_dealloc, /*tp_dealloc*/
+    0,                                  /*tp_print*/
+    0,                                  /*tp_getattr*/
+    0,                                  /*tp_setattr*/
+    0,                                  /*tp_compare*/
+    0,                                  /*tp_repr*/
+    0,                                  /*tp_as_number*/
+    0,                                  /*tp_as_sequence*/
+    0,                                  /*tp_as_mapping*/
+    0,                                  /*tp_hash*/
+    0,                                  /*tp_call*/
+    0,                                  /*tp_str*/
+    PyObject_GenericGetAttr,            /*tp_getattro*/
+    PyObject_GenericSetAttr,            /*tp_setattro*/
+    0,                                  /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,                 /*tp_flags*/
+    "Plugin object, providing a low-level API for running a Vamp plugin.", /*tp_doc*/
+    0,                                  /*tp_traverse*/
+    0,                                  /*tp_clear*/
+    0,                                  /*tp_richcompare*/
+    0,                                  /*tp_weaklistoffset*/
+    0,                                  /*tp_iter*/
+    0,                                  /*tp_iternext*/
+    PyPluginObject_methods,             /*tp_methods*/ 
+    PyPluginObject_members,             /*tp_members*/
+    0,                                  /*tp_getset*/
+    0,                                  /*tp_base*/
+    0,                                  /*tp_dict*/
+    0,                                  /*tp_descr_get*/
+    0,                                  /*tp_descr_set*/
+    0,                                  /*tp_dictoffset*/
+    0,                                  /*tp_init*/
+    PyType_GenericAlloc,                /*tp_alloc*/
+    0,                                  /*tp_new*/
+    PyObject_Del,                       /*tp_free*/
+    0,                                  /*tp_is_gc*/
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/PyPluginObject.h	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,68 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    VampyHost
+
+    Use Vamp audio analysis plugins in Python
+
+    Gyorgy Fazekas and Chris Cannam
+    Centre for Digital Music, Queen Mary, University of London
+    Copyright 2008-2014 Queen Mary, University of London
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and the authors
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef PYPLUGINOBJECT_H
+#define PYPLUGINOBJECT_H
+
+#include <Python.h>
+#include <vamp-hostsdk/Plugin.h>
+
+#include <string>
+
+struct PyPluginObject
+{
+    PyObject_HEAD
+    Vamp::Plugin *plugin;
+    bool isInitialised;
+    size_t channels;
+    size_t blockSize;
+    size_t stepSize;
+    PyObject *info;
+    int inputDomain;
+    PyObject *parameters;
+    PyObject *programs;
+};
+
+PyAPI_DATA(PyTypeObject) Plugin_Type;
+#define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type)
+
+PyAPI_FUNC(PyObject *)
+PyPluginObject_From_Plugin(Vamp::Plugin *);
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/PyRealTime.cpp	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,363 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    VampyHost
+
+    Use Vamp audio analysis plugins in Python
+
+    Gyorgy Fazekas and Chris Cannam
+    Centre for Digital Music, Queen Mary, University of London
+    Copyright 2008-2014 Queen Mary, University of London
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and the authors
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PyRealTime.h"
+
+#include <string>
+
+using namespace std;
+using namespace Vamp;
+
+/* CONSTRUCTOR: New RealTime object from sec and nsec */
+static PyObject*
+RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+    unsigned int sec = 0;
+    unsigned int nsec = 0;
+    double unary = 0;
+    const char *fmt = NULL;
+
+    if (
+        /// new RealTime from ('format',float) e.g. ('seconds',2.34123)   
+        !PyArg_ParseTuple(args, "|sd:RealTime.new ", 
+                          (const char *) &fmt, 
+                          (double *) &unary)    &&
+
+        /// new RealTime from (sec{int},nsec{int}) e.g. (2,34)
+        !PyArg_ParseTuple(args, "|II:RealTime.new ", 
+                          (unsigned int*) &sec, 
+                          (unsigned int*) &nsec) 
+                
+        ) { 
+        PyErr_SetString(PyExc_TypeError, 
+                        "RealTime initialised with wrong arguments.");
+        return NULL; 
+    }
+
+    // PyErr_Clear();
+
+    // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); 
+    RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0);
+        
+    if (self == NULL) return NULL;
+
+    self->rt = NULL;
+
+    if (sec == 0 && nsec == 0 && fmt == 0) 
+        self->rt = new RealTime();
+    else if (fmt == 0)
+        self->rt = new RealTime(sec,nsec);
+    else { 
+        /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3)
+        if (!string(fmt).compare("float") ||
+            !string(fmt).compare("seconds"))  
+            self->rt = new RealTime( 
+                RealTime::fromSeconds((double) unary)); 
+
+        if (!string(fmt).compare("milliseconds")) {
+            self->rt = new RealTime( 
+                RealTime::fromSeconds((double) unary / 1000.0)); }
+    }
+
+    if (!self->rt) { 
+        PyErr_SetString(PyExc_TypeError, 
+                        "RealTime initialised with wrong arguments.");
+        return NULL; 
+    }
+
+    return (PyObject *) self;
+}
+
+/* DESTRUCTOR: delete type object */
+static void
+RealTimeObject_dealloc(RealTimeObject *self)
+{
+    if (self->rt) delete self->rt;      //delete the C object
+    PyObject_Del(self); //delete the Python object (original)
+    /// this requires PyType_Ready() which fills ob_type
+    // self->ob_type->tp_free((PyObject*)self); 
+}
+
+/* RealTime Object's Methods */ 
+//these are internals not exposed by the module but the object
+
+/* Returns a Tuple containing sec and nsec values */
+static PyObject *
+RealTime_values(RealTimeObject *self)
+{
+    return Py_BuildValue("(ii)",self->rt->sec,self->rt->nsec);
+}
+
+/* Returns a Text representation */
+static PyObject *
+RealTime_toString(RealTimeObject *self, PyObject *args)
+{
+    return Py_BuildValue("s",self->rt->toText().c_str());
+}
+
+/* Frame representation */
+static PyObject *
+RealTime_toFrame(PyObject *self, PyObject *args)
+{
+    unsigned int samplerate;
+        
+    if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", 
+                           (unsigned int *) &samplerate )) {
+        PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required.");
+        return NULL;
+    }
+        
+    return Py_BuildValue("k", 
+                         RealTime::realTime2Frame( 
+                             *(const RealTime*) ((RealTimeObject*)self)->rt, 
+                             (unsigned int) samplerate));
+}
+
+/* Conversion of realtime to a double precision floating point value */
+/* ...in Python called by e.g. float(realtime) */
+static PyObject *
+RealTime_float(PyObject *s)
+{
+    double drt = ((double) ((RealTimeObject*)s)->rt->sec + 
+                  (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
+    return PyFloat_FromDouble(drt);     
+}
+
+
+/* Type object's (RealTime) methods table */
+static PyMethodDef RealTime_methods[] = 
+{
+    {"values",  (PyCFunction)RealTime_values,   METH_NOARGS,
+     PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
+
+    {"toString",        (PyCFunction)RealTime_toString, METH_NOARGS,
+     PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
+
+    {"toFrame", (PyCFunction)RealTime_toFrame,  METH_VARARGS,
+     PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
+
+    {"toFloat", (PyCFunction)RealTime_float,    METH_NOARGS,
+     PyDoc_STR("toFloat() -> Floating point representation.")},
+        
+    {NULL,              NULL}           /* sentinel */
+};
+
+
+/* Methods implementing protocols */ 
+// these functions are called by the interpreter 
+
+/* Object Protocol */
+
+static int
+RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
+{
+
+    if ( !string(name).compare("sec")) { 
+        self->rt->sec= (int) PyInt_AS_LONG(value);
+        return 0;
+    }
+
+    if ( !string(name).compare("nsec")) { 
+        self->rt->nsec= (int) PyInt_AS_LONG(value);
+        return 0;
+    }
+
+    return -1;
+}
+
+static PyObject *
+RealTime_getattr(RealTimeObject *self, char *name)
+{
+
+    if ( !string(name).compare("sec") ) { 
+        return PyInt_FromSsize_t(
+            (Py_ssize_t) self->rt->sec); 
+    } 
+
+    if ( !string(name).compare("nsec") ) { 
+        return PyInt_FromSsize_t(
+            (Py_ssize_t) self->rt->nsec); 
+    } 
+
+    return Py_FindMethod(RealTime_methods, 
+                         (PyObject *)self, name);
+}
+
+/* String representation called by e.g. str(realtime), print realtime*/
+static PyObject *
+RealTime_repr(PyObject *self)
+{
+    return Py_BuildValue("s",
+                         ((RealTimeObject*)self)->rt->toString().c_str());
+}
+
+
+/* Number Protocol */
+/// TODO: implement all methods available in Vamp::RealTime() objects
+
+static PyObject *
+RealTime_add(PyObject *s, PyObject *w)
+{
+    RealTimeObject *result = 
+        PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (result == NULL) return NULL;
+
+    result->rt = new RealTime(
+        *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
+    return (PyObject*)result;
+}
+
+static PyObject *
+RealTime_subtract(PyObject *s, PyObject *w)
+{
+    RealTimeObject *result = 
+        PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (result == NULL) return NULL;
+
+    result->rt = new RealTime(
+        *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
+    return (PyObject*)result;
+}
+
+static PyNumberMethods realtime_as_number = 
+{
+    RealTime_add,                       /*nb_add*/
+    RealTime_subtract,          /*nb_subtract*/
+    0,                                          /*nb_multiply*/
+    0,                                          /*nb_divide*/
+    0,                                          /*nb_remainder*/
+    0,                      /*nb_divmod*/
+    0,                          /*nb_power*/
+    0,                          /*nb_neg*/
+    0,                          /*nb_pos*/
+    0,                          /*(unaryfunc)array_abs,*/
+    0,                          /*nb_nonzero*/
+    0,                          /*nb_invert*/
+    0,                                  /*nb_lshift*/
+    0,                                  /*nb_rshift*/
+    0,                                  /*nb_and*/
+    0,                                  /*nb_xor*/
+    0,                                  /*nb_or*/
+    0,                      /*nb_coerce*/
+    0,                                          /*nb_int*/
+    0,                                  /*nb_long*/
+    (unaryfunc)RealTime_float,/*nb_float*/
+    0,                          /*nb_oct*/
+    0,                          /*nb_hex*/
+};
+
+/* REAL-TIME TYPE OBJECT */
+
+#define RealTime_alloc PyType_GenericAlloc
+#define RealTime_free PyObject_Del
+
+/* Doc:: 10.3 Type Objects */ /* static */ 
+PyTypeObject RealTime_Type = 
+{
+    PyObject_HEAD_INIT(NULL)
+    0,                          /*ob_size*/
+    "vampy.RealTime",           /*tp_name*/
+    sizeof(RealTimeObject),     /*tp_basicsize*/
+    0,                          /*tp_itemsize*/
+    /*          methods         */
+    (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
+    0,                                  /*tp_print*/
+    (getattrfunc)RealTime_getattr, /*tp_getattr*/
+    (setattrfunc)RealTime_setattr, /*tp_setattr*/
+    0,                             /*tp_compare*/
+    RealTime_repr,                 /*tp_repr*/
+    &realtime_as_number,        /*tp_as_number*/
+    0,                          /*tp_as_sequence*/
+    0,                          /*tp_as_mapping*/
+    0,                          /*tp_hash*/
+    0,                      /*tp_call*/
+    0,                      /*tp_str*/
+    0,                      /*tp_getattro*/
+    0,                      /*tp_setattro*/
+    0,                      /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,     /*tp_flags*/
+    "RealTime object, used for Vamp plugin timestamps.",      /*tp_doc*/
+    0,                      /*tp_traverse*/
+    0,                      /*tp_clear*/
+    0,                      /*tp_richcompare*/
+    0,                      /*tp_weaklistoffset*/
+    0,                      /*tp_iter*/
+    0,                      /*tp_iternext*/
+    RealTime_methods,       /*tp_methods*/ //TypeObject Methods
+    0,                      /*tp_members*/
+    0,                      /*tp_getset*/
+    0,                      /*tp_base*/
+    0,                      /*tp_dict*/
+    0,                      /*tp_descr_get*/
+    0,                      /*tp_descr_set*/
+    0,                      /*tp_dictoffset*/
+    0,                      /*tp_init*/
+    RealTime_alloc,         /*tp_alloc*/
+    RealTime_new,           /*tp_new*/
+    RealTime_free,          /*tp_free*/
+    0,                      /*tp_is_gc*/
+};
+
+
+
+/* PyRealTime C++ API */
+
+/*PyRealTime from RealTime*/
+PyObject* 
+PyRealTime_FromRealTime(const Vamp::RealTime& rt) {
+
+    RealTimeObject *self =
+        PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (self == NULL) return NULL;
+
+    self->rt = new RealTime(rt);
+    return (PyObject*) self;
+}
+
+/*RealTime* from PyRealTime*/
+const Vamp::RealTime*
+PyRealTime_AsRealTime (PyObject *self) { 
+
+    RealTimeObject *s = (RealTimeObject*) self; 
+
+    if (!PyRealTime_Check(s)) {
+        PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
+        cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
+        return NULL; }
+    return s->rt; 
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/PyRealTime.h	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,60 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    VampyHost
+
+    Use Vamp audio analysis plugins in Python
+
+    Gyorgy Fazekas and Chris Cannam
+    Centre for Digital Music, Queen Mary, University of London
+    Copyright 2008-2014 Queen Mary, University of London
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and the authors
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef PYREALTIME_H
+#define PYREALTIME_H
+
+#include <Python.h>
+#include <vamp-hostsdk/RealTime.h>
+
+typedef struct {
+    PyObject_HEAD
+    Vamp::RealTime *rt;
+} RealTimeObject; 
+
+PyAPI_DATA(PyTypeObject) RealTime_Type;
+
+#define PyRealTime_Check(v) PyObject_TypeCheck(v, &RealTime_Type)
+#define PyRealTime_AS_REALTIME(v) ((const RealTimeObject* const) (v))->rt
+
+PyAPI_FUNC(PyObject *) 
+PyRealTime_FromRealTime(const Vamp::RealTime&);
+
+PyAPI_FUNC(const Vamp::RealTime*) 
+PyRealTime_AsRealTime (PyObject *self);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/VectorConversion.cpp	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,318 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+  VampyHost
+
+  Use Vamp audio analysis plugins in Python
+
+  Gyorgy Fazekas and Chris Cannam
+  Centre for Digital Music, Queen Mary, University of London
+  Copyright 2008-2014 Queen Mary, University of London
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy,
+  modify, merge, publish, distribute, sublicense, and/or sell copies
+  of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+  Except as contained in this notice, the names of the Centre for
+  Digital Music; Queen Mary, University of London; and the authors
+  shall not be used in advertising or otherwise to promote the sale,
+  use or other dealings in this Software without prior written
+  authorization.
+*/
+
+#include <Python.h>
+
+#include "FloatConversion.h"
+#include "VectorConversion.h"
+
+#include <math.h>
+#include <float.h>
+
+using namespace std;
+
+/*  Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
+    (EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
+
+VectorConversion::VectorConversion() : 
+    m_error(false),
+    error(m_error) // const public reference for easy access
+{
+}
+
+VectorConversion::~VectorConversion()
+{
+}
+
+/// floating point numbers (TODO: check numpy.float128)
+float 
+VectorConversion::PyValue_To_Float(PyObject* pyValue) const
+{
+    if (FloatConversion::check(pyValue)) {
+        return FloatConversion::convert(pyValue);
+    }
+
+    setValueError("Conversion error: object" + PyValue_Get_TypeName(pyValue) +" is not float, int, or long.");
+    return 0.0;
+}
+
+vector<float> 
+VectorConversion::PyValue_To_FloatVector (PyObject *pyValue) const 
+{
+    /// numpy array
+    if (PyArray_CheckExact(pyValue)) 
+        return PyArray_To_FloatVector(pyValue);
+
+    /// python list of floats (backward compatible)
+    if (PyList_Check(pyValue)) {
+        return PyList_To_FloatVector(pyValue);
+    }
+
+    string msg = "Value is not list or array of floats";
+    setValueError(msg);
+#ifdef _DEBUG
+    cerr << "VectorConversion::PyValue_To_FloatVector failed. " << msg << endl;
+#endif
+    return vector<float>();
+}
+
+vector<float> 
+VectorConversion::PyList_To_FloatVector (PyObject *inputList) const 
+{
+    vector<float> v;
+	
+    if (!PyList_Check(inputList)) {
+        setValueError("Value is not a list");
+        return v;
+    } 
+
+    PyObject **pyObjectArray = PySequence_Fast_ITEMS(inputList);
+    int n = PyList_GET_SIZE(inputList);
+
+    for (int i = 0; i < n; ++i) {
+        v.push_back(PyValue_To_Float(pyObjectArray[i]));
+    }
+    
+    return v;
+}
+
+vector<float> 
+VectorConversion::PyArray_To_FloatVector (PyObject *pyValue) const 
+{
+    vector<float> v;
+	
+    if (!PyArray_Check(pyValue)) {
+        setValueError("Value is not an array");
+        return v;
+    } 
+
+    PyArrayObject* pyArray = (PyArrayObject*) pyValue;
+    PyArray_Descr* descr = PyArray_DESCR(pyArray);
+	
+    if (PyArray_DATA(pyArray) == 0 || descr == 0) {
+        string msg = "NumPy array with NULL data or descriptor pointer encountered.";
+        setValueError(msg);
+        return v;
+    }
+
+    if (PyArray_NDIM(pyArray) != 1) {
+        string msg = "NumPy array must be a one-dimensional vector.";
+        setValueError(msg);
+        return v;
+    }
+
+    /// check strides (useful if array is not continuous)
+    size_t strides =  *((size_t*) PyArray_STRIDES(pyArray));
+    
+    /// convert the array
+    switch (descr->type_num) {
+        
+    case NPY_FLOAT : // dtype='float32'
+        return PyArray_Convert<float,float>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
+    case NPY_DOUBLE : // dtype='float64'
+        return PyArray_Convert<float,double>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
+    case NPY_INT : // dtype='int'
+        return PyArray_Convert<float,int>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
+    case NPY_LONG : // dtype='long'
+        return PyArray_Convert<float,long>(PyArray_DATA(pyArray),PyArray_DIMS(pyArray)[0],strides);
+    default :
+        string msg = "Unsupported value type in NumPy array object.";
+        setValueError(msg);
+#ifdef _DEBUG
+        cerr << "VectorConversion::PyArray_To_FloatVector failed. Error: " << msg << endl;
+#endif			
+        return v;
+    }
+}
+
+vector<vector<float> >
+VectorConversion::Py2DArray_To_FloatVector (PyObject *pyValue) const 
+{
+    vector<vector<float> > v;
+	
+    if (!PyArray_Check(pyValue)) {
+        setValueError("Value is not an array");
+        return v;
+    } 
+
+    PyArrayObject* pyArray = (PyArrayObject*) pyValue;
+    PyArray_Descr* descr = PyArray_DESCR(pyArray);
+	
+    if (PyArray_DATA(pyArray) == 0 || descr == 0) {
+        string msg = "NumPy array with NULL data or descriptor pointer encountered.";
+        setValueError(msg);
+        return v;
+    }
+
+    if (PyArray_NDIM(pyArray) != 2) {
+        string msg = "NumPy array must be a two-dimensional matrix.";
+        setValueError(msg);
+        return v;
+    }
+
+    /// check strides (useful if array is not continuous)
+    size_t *strideptr =  (size_t*) PyArray_STRIDES(pyArray);
+    
+    /// convert the array
+    for (int i = 0; i < PyArray_DIMS(pyArray)[0]; ++i) {
+
+        vector<float> vv;
+        
+        switch (descr->type_num) {
+        
+        case NPY_FLOAT : // dtype='float32'
+            vv = PyArray_Convert<float,float>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
+            break;
+        case NPY_DOUBLE : // dtype='float64'
+            vv = PyArray_Convert<float,double>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
+            break;
+        case NPY_INT : // dtype='int'
+            vv = PyArray_Convert<float,int>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
+            break;
+        case NPY_LONG : // dtype='long'
+            vv = PyArray_Convert<float,long>(PyArray_GETPTR2(pyArray, i, 0),PyArray_DIMS(pyArray)[1],strideptr[1]);
+            break;
+        default :
+            string msg = "Unsupported value type in NumPy array object.";
+            cerr << "VectorConversion::PyArray_To_FloatVector failed (value type = " << descr->type_num << "). Error: " << msg << endl;
+            setValueError(msg);
+            return v;
+        }
+
+        v.push_back(vv);
+    }
+
+    return v;
+}
+
+PyObject *
+VectorConversion::PyArray_From_FloatVector(const vector<float> &v) const
+{
+    npy_intp ndims[1];
+    ndims[0] = (int)v.size();
+    PyObject *arr = PyArray_SimpleNew(1, ndims, NPY_FLOAT);
+    float *data = (float *)PyArray_DATA((PyArrayObject *)arr);
+    for (int i = 0; i < ndims[0]; ++i) {
+        data[i] = v[i];
+    }
+    return arr;
+}
+
+PyObject *
+VectorConversion::PyValue_From_StringVector(const vector<string> &v) const
+{
+    PyObject *pyList = PyList_New(v.size());
+    for (size_t i = 0; i < v.size(); ++i) {
+        PyObject *pyStr = PyString_FromString(v[i].c_str());
+        PyList_SET_ITEM(pyList, i, pyStr);
+    }
+    return pyList;
+}
+
+
+/* Error handling */
+
+void
+VectorConversion::setValueError (string message) const
+{
+    m_error = true;
+    m_errorQueue.push(ValueError(message));
+}
+
+/// return a reference to the last error or creates a new one.
+ValueError&
+VectorConversion::lastError() const 
+{
+    m_error = false;
+    if (!m_errorQueue.empty()) return m_errorQueue.back();
+    else {
+        m_errorQueue.push(ValueError("Type conversion error."));
+        return m_errorQueue.back();
+    }
+}
+
+/// helper function to iterate over the error message queue:
+/// pops the oldest item
+ValueError 
+VectorConversion::getError() const
+{
+    if (!m_errorQueue.empty()) {
+        ValueError e = m_errorQueue.front();
+        m_errorQueue.pop();
+        if (m_errorQueue.empty()) m_error = false;
+        return e;
+    }
+    else {
+        m_error = false;
+        return ValueError();
+    }
+}
+
+/* Utilities */
+
+/// get the type name of an object
+string
+VectorConversion::PyValue_Get_TypeName(PyObject* pyValue) const
+{
+    PyObject *pyType = PyObject_Type(pyValue);
+    if (!pyType) 
+    {
+        cerr << "Warning: Object type name could not be found." << endl;
+        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+        return string ("< unknown type >");
+    }
+    PyObject *pyString = PyObject_Str(pyType);
+    if (!pyString)
+    {
+        cerr << "Warning: Object type name could not be found." << endl;
+        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+        Py_CLEAR(pyType);
+        return string ("< unknown type >");
+    }
+    char *cstr = PyString_AS_STRING(pyString);
+    if (!cstr)
+    {
+        cerr << "Warning: Object type name could not be found." << endl;
+        if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+        Py_DECREF(pyType);
+        Py_CLEAR(pyString);
+        return string("< unknown type >");
+    }
+    Py_DECREF(pyType);
+    Py_DECREF(pyString);
+    return string(cstr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/VectorConversion.h	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,139 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+  VampyHost
+
+  Use Vamp audio analysis plugins in Python
+
+  Gyorgy Fazekas and Chris Cannam
+  Centre for Digital Music, Queen Mary, University of London
+  Copyright 2008-2014 Queen Mary, University of London
+  
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy,
+  modify, merge, publish, distribute, sublicense, and/or sell copies
+  of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+  Except as contained in this notice, the names of the Centre for
+  Digital Music; Queen Mary, University of London; and the authors
+  shall not be used in advertising or otherwise to promote the sale,
+  use or other dealings in this Software without prior written
+  authorization.
+*/
+
+/*
+  VectorConversion: A handful of type safe conversion utilities
+  between Python types and C++ vectors.
+*/
+
+#ifndef VAMPYHOST_VECTOR_CONVERSION_H
+#define VAMPYHOST_VECTOR_CONVERSION_H
+
+#include <Python.h>
+
+// NumPy is required here
+#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
+#define NO_IMPORT_ARRAY
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include "numpy/arrayobject.h"
+
+#include <vector>
+#include <queue>
+#include <string>
+#include <sstream>
+#include <iostream>
+	
+// Data
+class ValueError
+{
+public:
+    ValueError() {}
+    ValueError(std::string m) : message(m) {}
+    std::string location;
+    std::string message;
+    std::string str() const { 
+        return (location.empty()) ? message : message + "\nLocation: " + location;}
+    template<typename V> ValueError &operator<< (const V& v)
+    {
+        std::ostringstream ss;
+        ss << v;
+        location += ss.str();
+        return *this;
+    }
+};
+
+class VectorConversion
+{
+public:
+    VectorConversion();
+    ~VectorConversion();
+
+    ValueError getError() const;
+
+    std::vector<float> PyValue_To_FloatVector (PyObject*) const;
+    std::vector<float> PyArray_To_FloatVector (PyObject *) const;
+    std::vector<float> PyList_To_FloatVector (PyObject*) const;
+    std::vector<std::vector<float> > Py2DArray_To_FloatVector (PyObject *) const;
+    
+    PyObject *PyValue_From_StringVector(const std::vector<std::string> &) const;
+    PyObject *PyArray_From_FloatVector(const std::vector<float> &) const;
+
+private:
+    std::string PyValue_Get_TypeName(PyObject*) const;
+    float PyValue_To_Float(PyObject*) const;
+
+    /// Convert DTYPE type 1D NumpyArray to std::vector<RET>
+    template<typename RET, typename DTYPE>
+    std::vector<RET> PyArray_Convert(void* raw_data_ptr,
+                                     int length,
+                                     size_t strides) const {
+
+        std::vector<RET> v(length);
+		
+        /// check if the array is continuous, if not use strides info
+        if (sizeof(DTYPE) != strides) {
+#ifdef _DEBUG_VALUES
+            cerr << "Warning: discontinuous numpy array. Strides: " << strides << " bytes. sizeof(dtype): " << sizeof(DTYPE) << endl;
+#endif
+            char* data = (char*) raw_data_ptr;
+            for (int i = 0; i < length; ++i){
+                v[i] = (RET)(*((DTYPE*)data));
+                data += strides;
+            }
+            return v;
+        }
+
+        DTYPE* data = (DTYPE*) raw_data_ptr;
+        for (int i = 0; i < length; ++i){
+            v[i] = (RET)data[i];
+        }
+
+        return v;
+    }
+
+private:
+    mutable bool m_error;
+    mutable std::queue<ValueError> m_errorQueue;
+	
+    void setValueError(std::string) const;
+    ValueError& lastError() const;
+    
+public:
+    const bool& error;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/vampyhost-junk.cpp	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,170 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+// Moving stuff around 
+
+static PyObject *
+vampyhost_process(PyObject *self, PyObject *args)
+{
+//check if the plugin has been initialised
+//obtain sample Rate: maybe library:identifier:channels:stepSize:blockSize
+    PyObject *pyPluginHandle;
+    PyObject *pyBuffer;
+
+    if (!PyArg_ParseTuple(args, "OO", 
+			  &pyPluginHandle,	// C object holding a pointer to a plugin and its descriptor
+			  &pyBuffer)) {		// Audio data
+	PyErr_SetString(PyExc_TypeError,
+			"Required: plugin handle, buffer, timestmap.");
+	return NULL; }
+
+    string *key;	
+    Plugin *plugin; 
+    long frame = 0;
+
+    if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
+	PyErr_SetString(PyExc_AttributeError,
+			"Invalid or already deleted plugin handle.");
+	return NULL; }
+
+    PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
+
+    if (!pd->isInitialised) {
+	PyErr_SetString(PyExc_StandardError,
+			"Plugin has not been initialised.");
+	return NULL; }
+
+    size_t channels =  pd->channels;	
+    size_t blockSize = pd->blockSize;
+
+/*
+  Handle the case when we get the data as a character buffer
+  Handle SampleFormats: int16, float32
+	
+*/
+		
+    if (PyString_Check(pyBuffer)) {
+	cerr << ">>> String obj passed in." << endl;
+    }
+
+//	size_t chlen = sizeof(short) / sizeof(char); 
+
+    //Assume interleaved signed 16-bit PCM data
+
+    //int *intch = new int*[buflen/2];
+    //int *intch = (int*) PyString_AS_STRING(pyBuffer);
+    //short *tmpch = 
+    //reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
+
+    typedef char int16[2]; //can we trust sizeof(short) = 2 ?
+    size_t sample_size = sizeof(int16);
+
+    long buflen = (long) PyString_GET_SIZE(pyBuffer);
+
+    size_t input_length = 
+	static_cast <size_t> (buflen/channels/sample_size);
+
+    if (input_length == pd->blockSize) {
+	cerr << ">>> A full block has been passed in." << endl; }
+
+    int16 *input = 
+	reinterpret_cast <int16*> (PyString_AS_STRING(pyBuffer));
+	
+    // int16 *input = new int16[buflen/sample_size];
+    // input = reinterpret_cast <int16*> (PyString_AS_STRING(pyBuffer));
+	
+    // short *input = 
+    // reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
+	
+    //float ffirst = 
+    //static_cast <float> (*input[1000]) /
+    //static_cast <float> (SHRT_MAX);
+
+//	int *proba[10]; -> pointer array
+    int *proba = new int[10]; // -> actual array of ints
+    int p = 234;
+    proba[1]=p;
+    size_t chlen = (size_t) buflen/2;
+    //short smax = SHRT_MAX;
+    cerr 
+	<< " c: " << sizeof(char) 	
+	<< " s: " << sizeof(short) 
+	//<< " i16: " << sizeof(int16) 
+	<< " i:" << sizeof(int) 
+	<< " float:" << sizeof(float)
+	<< " [proba]: " << proba[1]
+	//<< " ffirst: " << ffirst 
+	<< endl; 
+
+    //vector<int> *intch = (vector<int>*) PyString_AS_STRING(pyBuffer);
+    //size_t chlen = intch->size();
+    //cerr << ">>>Size of ch buffer: " << chlen << endl;
+	
+    //convert int16 PCM data to 32-bit floats
+    float **plugbuf = new float*[channels];
+    float smax = static_cast <float> (SHRT_MAX);
+		
+    for (size_t c = 0; c < channels; ++c) {
+
+	plugbuf[c] = new float[blockSize+2];
+  
+      	size_t j = 0;
+        while (j < input_length) {
+	    //int *v = (*int) input[j * channels + c];
+	    //int value = 5;//input[j * channels + c];
+	    // short *v = (short*) input+j;
+	    // short value = *v;
+	    //int *v = (int*) input+j;
+	    int *v = new int;
+	    *v = 0;
+	    char *wc = (char*) v;
+	    char *ic = (char*) input[j];
+	    wc=wc+2;
+	    *wc = *ic; 
+	    wc++; ic++;
+	    *wc = *ic; 
+
+	    int value = *v;
+
+	    plugbuf[c][j] =  static_cast <float> (value/100000);
+// works if short=2	static_cast <float> (*input[j * channels + c]) / smax;
+//			static_cast <float> (input[j * channels + c]) / smax;
+	    ++j; 
+        }
+        while (j < blockSize) {
+            plugbuf[c][j] = 0.0f;
+            ++j;
+        }
+
+	//}
+    }	
+
+    const char *output = reinterpret_cast <const char*> (plugbuf[0]);
+    Py_ssize_t len = (Py_ssize_t) channels*blockSize*4;
+	
+    PyObject* pyReturnBuffer = 
+	PyString_FromStringAndSize(output,len);
+
+    return pyReturnBuffer;
+
+
+/* NOW return the data in a PyBuffer
+
+ */
+
+/*	
+	char* test =  PyString_AS_STRING(pyBuffer);
+	cerr << "Passed in: " << buflen << " str: " << test << endl;
+
+//convert the buffer to plugbuf
+		
+//plugin->process
+// (plugbuf, RealTime::frame2RealTime(frame, samplerate))
+
+for(size_t k=0; k<channels; k++){
+delete[] plugbuf[k];
+}
+delete[] plugbuf;
+*/
+    return pyReturnBuffer;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/native/vampyhost.cpp	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,297 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    VampyHost
+
+    Use Vamp audio analysis plugins in Python
+
+    Gyorgy Fazekas and Chris Cannam
+    Centre for Digital Music, Queen Mary, University of London
+    Copyright 2008-2014 Queen Mary, University of London
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and the authors
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+// include for python extension module: must be first
+#include <Python.h>
+
+// define a unique API pointer 
+#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include "numpy/arrayobject.h"
+
+#include "PyRealTime.h"
+#include "PyPluginObject.h"
+
+#include "vamp-hostsdk/PluginHostAdapter.h"
+#include "vamp-hostsdk/PluginChannelAdapter.h"
+#include "vamp-hostsdk/PluginInputDomainAdapter.h"
+#include "vamp-hostsdk/PluginLoader.h"
+
+#include "VectorConversion.h"
+#include "PyRealTime.h"
+
+#include <iostream>
+#include <string>
+
+#include <cmath>
+
+using namespace std;
+using namespace Vamp;
+using namespace Vamp::HostExt;
+
+static PyObject *
+enumeratePlugins(PyObject *self, PyObject *)
+{
+    PluginLoader *loader = PluginLoader::getInstance();
+    vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
+    VectorConversion conv;
+    return conv.PyValue_From_StringVector(plugins);
+}
+
+static PyObject *
+getPluginPath(PyObject *self, PyObject *)
+{
+    vector<string> path = PluginHostAdapter::getPluginPath();
+    VectorConversion conv;
+    return conv.PyValue_From_StringVector(path);
+}
+
+static string toPluginKey(PyObject *pyPluginKey)
+{
+    // convert to stl string
+    string pluginKey(PyString_AS_STRING(pyPluginKey));
+
+    // check pluginKey validity
+    string::size_type ki = pluginKey.find(':');
+    if (ki == string::npos) {
+        PyErr_SetString(PyExc_TypeError,
+                        "Plugin key must be of the form library:identifier");
+        return "";
+    }
+
+    return pluginKey;
+}
+
+static PyObject *
+getLibraryFor(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+
+    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "getLibraryPathForPlugin() takes plugin key (string) argument");
+        return 0; }
+
+    string pluginKey = toPluginKey(pyPluginKey);
+    if (pluginKey == "") return 0;
+    
+    PluginLoader *loader = PluginLoader::getInstance();
+    string path = loader->getLibraryPathForPlugin(pluginKey);
+    PyObject *pyPath = PyString_FromString(path.c_str());
+    return pyPath;
+}
+
+static PyObject *
+getPluginCategory(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+
+    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "getPluginCategory() takes plugin key (string) argument");
+        return 0; }
+
+    string pluginKey = toPluginKey(pyPluginKey);
+    if (pluginKey == "") return 0;
+
+    PluginLoader *loader = PluginLoader::getInstance();
+    PluginLoader::PluginCategoryHierarchy
+        category = loader->getPluginCategory(pluginKey);
+
+    VectorConversion conv;
+    return conv.PyValue_From_StringVector(category);
+}
+
+static PyObject *
+getOutputList(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+
+    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "getOutputList() takes plugin key (string) argument");
+        return 0; }
+
+    Plugin::OutputList outputs;
+
+    string pluginKey = toPluginKey(pyPluginKey);
+    if (pluginKey == "") return 0;
+
+    PluginLoader *loader = PluginLoader::getInstance();
+
+    Plugin *plugin = loader->loadPlugin(pluginKey, 48000, 0);
+    if (!plugin) {
+        string pyerr("Failed to load plugin: "); pyerr += pluginKey;
+        PyErr_SetString(PyExc_TypeError,pyerr.c_str());
+        return 0;
+    }
+
+    outputs = plugin->getOutputDescriptors();
+
+    PyObject *pyList = PyList_New(outputs.size());
+
+    for (size_t i = 0; i < outputs.size(); ++i) {
+        PyObject *pyOutputId =
+            PyString_FromString(outputs[i].identifier.c_str());
+        PyList_SET_ITEM(pyList, i, pyOutputId);
+    }
+
+    return pyList;
+}
+
+static PyObject *
+loadPlugin(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+    float inputSampleRate;
+    int adapterFlags;
+
+    if (!PyArg_ParseTuple(args, "Sfn",
+                          &pyPluginKey,
+                          &inputSampleRate,
+                          &adapterFlags)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "loadPlugin() takes plugin key (string), sample rate (float), and adapter flags (int) arguments");
+        return 0; }
+
+    string pluginKey = toPluginKey(pyPluginKey);
+    if (pluginKey == "") return 0;
+
+    PluginLoader *loader = PluginLoader::getInstance();
+
+    Plugin *plugin = loader->loadPlugin(pluginKey,
+                                        inputSampleRate,
+                                        adapterFlags);
+    if (!plugin) {
+        string pyerr("Failed to load plugin: "); pyerr += pluginKey;
+        PyErr_SetString(PyExc_TypeError,pyerr.c_str());
+        return 0;
+    }
+
+    return PyPluginObject_From_Plugin(plugin);
+}
+
+// module methods table
+static PyMethodDef vampyhost_methods[] = {
+
+    {"listPlugins", enumeratePlugins, METH_NOARGS,
+     "listPlugins() -> Return a list of the plugin keys of all installed Vamp plugins." },
+
+    {"getPluginPath", getPluginPath, METH_NOARGS,
+     "getPluginPath() -> Return a list of directories which will be searched for Vamp plugins. This may be changed by setting the VAMP_PATH environment variable."},
+
+    {"getCategoryOf", getPluginCategory, METH_VARARGS,
+     "getCategoryOf(pluginKey) -> Return the category of a Vamp plugin given its key, if known. The category is expressed as a list of nested types from least to most specific."},
+
+    {"getLibraryFor", getLibraryFor, METH_VARARGS,
+     "getLibraryFor(pluginKey) -> Return the file path of the Vamp plugin library in which the given plugin key is found, or an empty string if the plugin is not installed."},
+
+    {"getOutputsOf", getOutputList, METH_VARARGS,
+     "getOutputsOf(pluginKey) -> Return a list of the output identifiers of the plugin with the given key, if installed."},
+
+    {"loadPlugin", loadPlugin, METH_VARARGS,
+     "loadPlugin(pluginKey, samplerate) -> Load the plugin that has the given key, if installed, and return the plugin object."},
+
+    {0, 0}              /* sentinel */
+};
+
+PyDoc_STRVAR(module_doc, "Load and run Vamp audio analysis plugins.");
+
+static int
+setint(PyObject *d, const char *name, int value)
+{
+    PyObject *v;
+    int err;
+    v = PyInt_FromLong((long)value);
+    err = PyDict_SetItemString(d, name, v);
+    Py_XDECREF(v);
+    return err;
+}
+
+/* Initialization function for the module (*must* be called initxx) */
+
+// module initialization (includes extern C {...} as necessary)
+PyMODINIT_FUNC
+initvampyhost(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&RealTime_Type) < 0) return;
+    if (PyType_Ready(&Plugin_Type) < 0) return;
+
+    m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
+    if (!m) {
+        cerr << "ERROR: initvampyhost: Failed to initialise module" << endl;
+        return;
+    }
+
+    import_array();
+
+    PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type);
+    PyModule_AddObject(m, "Plugin", (PyObject *)&Plugin_Type);
+
+    // Some enum types
+    PyObject *dict = PyModule_GetDict(m);
+    if (!dict) {
+        cerr << "ERROR: initvampyhost: Failed to obtain module dictionary" << endl;
+        return;
+    }
+
+    if (setint(dict, "OneSamplePerStep",
+               Plugin::OutputDescriptor::OneSamplePerStep) < 0 ||
+        setint(dict, "FixedSampleRate",
+               Plugin::OutputDescriptor::FixedSampleRate) < 0 ||
+        setint(dict, "VariableSampleRate",
+               Plugin::OutputDescriptor::VariableSampleRate) < 0 ||
+        setint(dict, "TimeDomain",
+               Plugin::TimeDomain) < 0 ||
+        setint(dict, "FrequencyDomain",
+               Plugin::FrequencyDomain) < 0 ||
+        setint(dict, "AdaptNone",
+               0) < 0 ||
+        setint(dict, "AdaptChannelCount",
+               PluginLoader::ADAPT_CHANNEL_COUNT) < 0 ||
+        setint(dict, "AdaptBufferSize",
+               PluginLoader::ADAPT_BUFFER_SIZE) < 0 ||
+        setint(dict, "AdaptAllSafe",
+               PluginLoader::ADAPT_ALL_SAFE) < 0 ||
+        setint(dict, "AdaptAll",
+               PluginLoader::ADAPT_ALL) < 0) {
+        cerr << "ERROR: initvampyhost: Failed to add enums to module dictionary" << endl;
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_metadata.py	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,28 @@
+
+import vampyhost as vh
+
+testPluginKey = "vamp-test-plugin:vamp-test-plugin"
+
+##!!! could use: plugin version
+
+def test_list():
+    plugins = vh.listPlugins()
+    if testPluginKey not in plugins:
+        print("Test plugin " + testPluginKey + " not installed or not returned by enumerate: can't run any tests without it")
+    assert testPluginKey in plugins
+
+def test_path():
+    path = vh.getPluginPath()
+    assert len(path) > 0
+
+def test_getlibrary():
+    lib = vh.getLibraryFor(testPluginKey)
+    assert lib.find("vamp-test-plugin") >= 0
+    try:
+        lib = vh.getLibraryFor("not a well-formatted plugin key")
+        assert False
+    except TypeError:
+        pass
+    lib = vh.getLibraryFor("nonexistent-library:nonexistent-plugin")
+    assert lib == ""
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_plugin_metadata.py	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,59 @@
+
+import vampyhost as vh
+
+testPluginKey = "vamp-test-plugin:vamp-test-plugin"
+
+rate = 44100
+
+def test_getoutputlist():
+    outputs = vh.getOutputsOf(testPluginKey)
+    assert len(outputs) == 9
+    assert "input-summary" in outputs
+
+def test_inputdomain():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    assert plug.inputDomain == vh.TimeDomain
+
+def test_info():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    assert plug.info["identifier"] == "vamp-test-plugin"
+    
+def test_parameterdescriptors():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    assert plug.parameters[0]["identifier"] == "produce_output"
+    
+def test_setparameter():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    assert plug.parameters[0]["identifier"] == "produce_output"
+    assert plug.parameters[0]["defaultValue"] == 1
+    assert plug.getParameterValue("produce_output") == plug.parameters[0]["defaultValue"]
+    assert plug.setParameterValue("produce_output", 0) == True
+    assert plug.getParameterValue("produce_output") == 0
+    assert plug.setParameterValues({ "produce_output": 1 }) == True
+    assert plug.getParameterValue("produce_output") == 1
+    try:
+        plug.setParameterValue("produce_output", "fish")
+        assert False
+    except TypeError:
+        pass
+    try:
+        plug.setParameterValue(4, 0)
+        assert False
+    except TypeError:
+        pass
+    try:
+        plug.setParameterValue("steak", 0)
+        assert False
+    except StandardError:
+        pass
+    try:
+        plug.getParameterValue(4)
+        assert False
+    except TypeError:
+        pass
+    try:
+        plug.getParameterValue("steak")
+        assert False
+    except StandardError:
+        pass
+            
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_process.py	Wed Jan 14 08:30:47 2015 +0000
@@ -0,0 +1,116 @@
+
+import vampyhost as vh
+import numpy as np
+
+testPluginKey = "vamp-test-plugin:vamp-test-plugin"
+
+##!!! todo: support for, and test for, correct version of test plugin (with parameter)
+
+rate = 44100
+
+def test_load_unload():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    plug.unload()
+    try:
+        plug.unload() # should throw but not crash
+        assert(False)
+    except AttributeError:
+        pass
+
+def test_get_set_parameter():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    value = plug.getParameterValue("produce_output")
+    assert(value == 1.0)
+    plug.setParameterValue("produce_output", 0.0)
+    value = plug.getParameterValue("produce_output")
+    assert(value == 0.0)
+    
+def test_process_without_initialise():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    try:
+        plug.process([[1,2,3,4]], vh.RealTime(0, 0))
+        assert False
+    except StandardError:
+        pass
+
+def test_process_input_format():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    plug.initialise(2, 4, 4) # channels, stepsize, blocksize
+    result = plug.process([[1,2,3,4],[5,6,7,8]], vh.RealTime(0, 0))
+    result = plug.process([np.array([1,2,3,4]),np.array([5,6,7,8])], vh.RealTime(0, 0))
+    result = plug.process(np.array([[1,2,3,4],[5,6,7,8]]), vh.RealTime(0, 0))
+    try:
+        # Wrong number of channels
+        result = plug.process(np.array([[1,2,3,4]]), vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    try:
+        # Wrong number of samples per channel
+        result = plug.process(np.array([[1,2,3],[4,5,6]]), vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    try:
+        # Differing numbers of samples per channel
+        result = plug.process(np.array([[1,2,3,4],[5,6,7]]), vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+
+def test_process_output_1ch():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    plug.initialise(1, 2, 2)
+    try:
+        # Too many channels
+        result = plug.process([[3,4],[5,6]], vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    result = plug.process([[3,3]], vh.RealTime(0, 0))
+    assert result[8] == [ { "label" : "", "values" : np.array([5.0]) } ]
+    result = plug.process([[3,0]], vh.RealTime(0, 0))
+    assert result[8] == [ { "label" : "", "values" : np.array([4.0]) } ]
+
+def test_process_output_2ch():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    plug.initialise(2, 2, 2)
+    try:
+        # Too few channels
+        result = plug.process([[3,4]], vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    try:
+        # Too many channels
+        result = plug.process([[3,4],[5,6],[7,8]], vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    result = plug.process([[3,3],[4,4]], vh.RealTime(0, 0))
+    assert (result[8][0]["values"] == np.array([5.0,6.0])).all()
+    result = plug.process([[3,0],[4,0]], vh.RealTime(0, 0))
+    assert (result[8][0]["values"] == np.array([4.0,5.0])).all()
+
+def test_process_output_3ch():
+    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
+    plug.initialise(3, 2, 2)
+    try:
+        # Too few channels
+        result = plug.process([[3,4],[5,6]], vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    try:
+        # Too many channels
+        result = plug.process([[3,4],[5,6],[7,8],[9,10]], vh.RealTime(0, 0))
+        assert False
+    except TypeError:
+        pass
+    result = plug.process([[3,3],[4,4],[5,5]], vh.RealTime(0, 0))
+    assert (result[8][0]["values"] == np.array([5.0,6.0,7.0])).all()
+    result = plug.process([[3,0],[4,0],[5,0]], vh.RealTime(0, 0))
+    assert (result[8][0]["values"] == np.array([4.0,5.0,6.0])).all()
+
+
+    
--- a/test_metadata.py	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-
-import vampyhost as vh
-
-testPluginKey = "vamp-test-plugin:vamp-test-plugin"
-
-##!!! could use: plugin version
-
-def test_list():
-    plugins = vh.listPlugins()
-    if testPluginKey not in plugins:
-        print("Test plugin " + testPluginKey + " not installed or not returned by enumerate: can't run any tests without it")
-    assert testPluginKey in plugins
-
-def test_path():
-    path = vh.getPluginPath()
-    assert len(path) > 0
-
-def test_getlibrary():
-    lib = vh.getLibraryFor(testPluginKey)
-    assert lib.find("vamp-test-plugin") >= 0
-    try:
-        lib = vh.getLibraryFor("not a well-formatted plugin key")
-        assert False
-    except TypeError:
-        pass
-    lib = vh.getLibraryFor("nonexistent-library:nonexistent-plugin")
-    assert lib == ""
-    
--- a/test_plugin_metadata.py	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-
-import vampyhost as vh
-
-testPluginKey = "vamp-test-plugin:vamp-test-plugin"
-
-rate = 44100
-
-def test_getoutputlist():
-    outputs = vh.getOutputsOf(testPluginKey)
-    assert len(outputs) == 9
-    assert "input-summary" in outputs
-
-def test_inputdomain():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    assert plug.inputDomain == vh.TimeDomain
-
-def test_info():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    assert plug.info["identifier"] == "vamp-test-plugin"
-    
-def test_parameterdescriptors():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    assert plug.parameters[0]["identifier"] == "produce_output"
-    
-def test_setparameter():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    assert plug.parameters[0]["identifier"] == "produce_output"
-    assert plug.parameters[0]["defaultValue"] == 1
-    assert plug.getParameterValue("produce_output") == plug.parameters[0]["defaultValue"]
-    assert plug.setParameterValue("produce_output", 0) == True
-    assert plug.getParameterValue("produce_output") == 0
-    assert plug.setParameterValues({ "produce_output": 1 }) == True
-    assert plug.getParameterValue("produce_output") == 1
-    try:
-        plug.setParameterValue("produce_output", "fish")
-        assert False
-    except TypeError:
-        pass
-    try:
-        plug.setParameterValue(4, 0)
-        assert False
-    except TypeError:
-        pass
-    try:
-        plug.setParameterValue("steak", 0)
-        assert False
-    except StandardError:
-        pass
-    try:
-        plug.getParameterValue(4)
-        assert False
-    except TypeError:
-        pass
-    try:
-        plug.getParameterValue("steak")
-        assert False
-    except StandardError:
-        pass
-            
--- a/test_process.py	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-
-import vampyhost as vh
-import numpy as np
-
-testPluginKey = "vamp-test-plugin:vamp-test-plugin"
-
-##!!! todo: support for, and test for, correct version of test plugin (with parameter)
-
-rate = 44100
-
-def test_load_unload():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    plug.unload()
-    try:
-        plug.unload() # should throw but not crash
-        assert(False)
-    except AttributeError:
-        pass
-
-def test_get_set_parameter():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    value = plug.getParameterValue("produce_output")
-    assert(value == 1.0)
-    plug.setParameterValue("produce_output", 0.0)
-    value = plug.getParameterValue("produce_output")
-    assert(value == 0.0)
-    
-def test_process_without_initialise():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    try:
-        plug.process([[1,2,3,4]], vh.RealTime(0, 0))
-        assert False
-    except StandardError:
-        pass
-
-def test_process_input_format():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    plug.initialise(2, 4, 4) # channels, stepsize, blocksize
-    result = plug.process([[1,2,3,4],[5,6,7,8]], vh.RealTime(0, 0))
-    result = plug.process([np.array([1,2,3,4]),np.array([5,6,7,8])], vh.RealTime(0, 0))
-    result = plug.process(np.array([[1,2,3,4],[5,6,7,8]]), vh.RealTime(0, 0))
-    try:
-        # Wrong number of channels
-        result = plug.process(np.array([[1,2,3,4]]), vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    try:
-        # Wrong number of samples per channel
-        result = plug.process(np.array([[1,2,3],[4,5,6]]), vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    try:
-        # Differing numbers of samples per channel
-        result = plug.process(np.array([[1,2,3,4],[5,6,7]]), vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-
-def test_process_output_1ch():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    plug.initialise(1, 2, 2)
-    try:
-        # Too many channels
-        result = plug.process([[3,4],[5,6]], vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    result = plug.process([[3,3]], vh.RealTime(0, 0))
-    assert result[8] == [ { "label" : "", "values" : np.array([5.0]) } ]
-    result = plug.process([[3,0]], vh.RealTime(0, 0))
-    assert result[8] == [ { "label" : "", "values" : np.array([4.0]) } ]
-
-def test_process_output_2ch():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    plug.initialise(2, 2, 2)
-    try:
-        # Too few channels
-        result = plug.process([[3,4]], vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    try:
-        # Too many channels
-        result = plug.process([[3,4],[5,6],[7,8]], vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    result = plug.process([[3,3],[4,4]], vh.RealTime(0, 0))
-    assert (result[8][0]["values"] == np.array([5.0,6.0])).all()
-    result = plug.process([[3,0],[4,0]], vh.RealTime(0, 0))
-    assert (result[8][0]["values"] == np.array([4.0,5.0])).all()
-
-def test_process_output_3ch():
-    plug = vh.loadPlugin(testPluginKey, rate, vh.AdaptNone)
-    plug.initialise(3, 2, 2)
-    try:
-        # Too few channels
-        result = plug.process([[3,4],[5,6]], vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    try:
-        # Too many channels
-        result = plug.process([[3,4],[5,6],[7,8],[9,10]], vh.RealTime(0, 0))
-        assert False
-    except TypeError:
-        pass
-    result = plug.process([[3,3],[4,4],[5,5]], vh.RealTime(0, 0))
-    assert (result[8][0]["values"] == np.array([5.0,6.0,7.0])).all()
-    result = plug.process([[3,0],[4,0],[5,0]], vh.RealTime(0, 0))
-    assert (result[8][0]["values"] == np.array([4.0,5.0,6.0])).all()
-
-
-    
--- a/vampyhost-junk.cpp	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-// Moving stuff around 
-
-static PyObject *
-vampyhost_process(PyObject *self, PyObject *args)
-{
-//check if the plugin has been initialised
-//obtain sample Rate: maybe library:identifier:channels:stepSize:blockSize
-    PyObject *pyPluginHandle;
-    PyObject *pyBuffer;
-
-    if (!PyArg_ParseTuple(args, "OO", 
-			  &pyPluginHandle,	// C object holding a pointer to a plugin and its descriptor
-			  &pyBuffer)) {		// Audio data
-	PyErr_SetString(PyExc_TypeError,
-			"Required: plugin handle, buffer, timestmap.");
-	return NULL; }
-
-    string *key;	
-    Plugin *plugin; 
-    long frame = 0;
-
-    if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
-	PyErr_SetString(PyExc_AttributeError,
-			"Invalid or already deleted plugin handle.");
-	return NULL; }
-
-    PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
-
-    if (!pd->isInitialised) {
-	PyErr_SetString(PyExc_StandardError,
-			"Plugin has not been initialised.");
-	return NULL; }
-
-    size_t channels =  pd->channels;	
-    size_t blockSize = pd->blockSize;
-
-/*
-  Handle the case when we get the data as a character buffer
-  Handle SampleFormats: int16, float32
-	
-*/
-		
-    if (PyString_Check(pyBuffer)) {
-	cerr << ">>> String obj passed in." << endl;
-    }
-
-//	size_t chlen = sizeof(short) / sizeof(char); 
-
-    //Assume interleaved signed 16-bit PCM data
-
-    //int *intch = new int*[buflen/2];
-    //int *intch = (int*) PyString_AS_STRING(pyBuffer);
-    //short *tmpch = 
-    //reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
-
-    typedef char int16[2]; //can we trust sizeof(short) = 2 ?
-    size_t sample_size = sizeof(int16);
-
-    long buflen = (long) PyString_GET_SIZE(pyBuffer);
-
-    size_t input_length = 
-	static_cast <size_t> (buflen/channels/sample_size);
-
-    if (input_length == pd->blockSize) {
-	cerr << ">>> A full block has been passed in." << endl; }
-
-    int16 *input = 
-	reinterpret_cast <int16*> (PyString_AS_STRING(pyBuffer));
-	
-    // int16 *input = new int16[buflen/sample_size];
-    // input = reinterpret_cast <int16*> (PyString_AS_STRING(pyBuffer));
-	
-    // short *input = 
-    // reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
-	
-    //float ffirst = 
-    //static_cast <float> (*input[1000]) /
-    //static_cast <float> (SHRT_MAX);
-
-//	int *proba[10]; -> pointer array
-    int *proba = new int[10]; // -> actual array of ints
-    int p = 234;
-    proba[1]=p;
-    size_t chlen = (size_t) buflen/2;
-    //short smax = SHRT_MAX;
-    cerr 
-	<< " c: " << sizeof(char) 	
-	<< " s: " << sizeof(short) 
-	//<< " i16: " << sizeof(int16) 
-	<< " i:" << sizeof(int) 
-	<< " float:" << sizeof(float)
-	<< " [proba]: " << proba[1]
-	//<< " ffirst: " << ffirst 
-	<< endl; 
-
-    //vector<int> *intch = (vector<int>*) PyString_AS_STRING(pyBuffer);
-    //size_t chlen = intch->size();
-    //cerr << ">>>Size of ch buffer: " << chlen << endl;
-	
-    //convert int16 PCM data to 32-bit floats
-    float **plugbuf = new float*[channels];
-    float smax = static_cast <float> (SHRT_MAX);
-		
-    for (size_t c = 0; c < channels; ++c) {
-
-	plugbuf[c] = new float[blockSize+2];
-  
-      	size_t j = 0;
-        while (j < input_length) {
-	    //int *v = (*int) input[j * channels + c];
-	    //int value = 5;//input[j * channels + c];
-	    // short *v = (short*) input+j;
-	    // short value = *v;
-	    //int *v = (int*) input+j;
-	    int *v = new int;
-	    *v = 0;
-	    char *wc = (char*) v;
-	    char *ic = (char*) input[j];
-	    wc=wc+2;
-	    *wc = *ic; 
-	    wc++; ic++;
-	    *wc = *ic; 
-
-	    int value = *v;
-
-	    plugbuf[c][j] =  static_cast <float> (value/100000);
-// works if short=2	static_cast <float> (*input[j * channels + c]) / smax;
-//			static_cast <float> (input[j * channels + c]) / smax;
-	    ++j; 
-        }
-        while (j < blockSize) {
-            plugbuf[c][j] = 0.0f;
-            ++j;
-        }
-
-	//}
-    }	
-
-    const char *output = reinterpret_cast <const char*> (plugbuf[0]);
-    Py_ssize_t len = (Py_ssize_t) channels*blockSize*4;
-	
-    PyObject* pyReturnBuffer = 
-	PyString_FromStringAndSize(output,len);
-
-    return pyReturnBuffer;
-
-
-/* NOW return the data in a PyBuffer
-
- */
-
-/*	
-	char* test =  PyString_AS_STRING(pyBuffer);
-	cerr << "Passed in: " << buflen << " str: " << test << endl;
-
-//convert the buffer to plugbuf
-		
-//plugin->process
-// (plugbuf, RealTime::frame2RealTime(frame, samplerate))
-
-for(size_t k=0; k<channels; k++){
-delete[] plugbuf[k];
-}
-delete[] plugbuf;
-*/
-    return pyReturnBuffer;
-
-}
--- a/vampyhost.cpp	Tue Jan 13 12:16:38 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    VampyHost
-
-    Use Vamp audio analysis plugins in Python
-
-    Gyorgy Fazekas and Chris Cannam
-    Centre for Digital Music, Queen Mary, University of London
-    Copyright 2008-2014 Queen Mary, University of London
-  
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
-    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and the authors
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-// include for python extension module: must be first
-#include <Python.h>
-
-// define a unique API pointer 
-#define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#include "numpy/arrayobject.h"
-
-#include "PyRealTime.h"
-#include "PyPluginObject.h"
-
-#include "vamp-hostsdk/PluginHostAdapter.h"
-#include "vamp-hostsdk/PluginChannelAdapter.h"
-#include "vamp-hostsdk/PluginInputDomainAdapter.h"
-#include "vamp-hostsdk/PluginLoader.h"
-
-#include "VectorConversion.h"
-#include "PyRealTime.h"
-
-#include <iostream>
-#include <string>
-
-#include <cmath>
-
-using namespace std;
-using namespace Vamp;
-using namespace Vamp::HostExt;
-
-static PyObject *
-enumeratePlugins(PyObject *self, PyObject *)
-{
-    PluginLoader *loader = PluginLoader::getInstance();
-    vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
-    VectorConversion conv;
-    return conv.PyValue_From_StringVector(plugins);
-}
-
-static PyObject *
-getPluginPath(PyObject *self, PyObject *)
-{
-    vector<string> path = PluginHostAdapter::getPluginPath();
-    VectorConversion conv;
-    return conv.PyValue_From_StringVector(path);
-}
-
-static string toPluginKey(PyObject *pyPluginKey)
-{
-    // convert to stl string
-    string pluginKey(PyString_AS_STRING(pyPluginKey));
-
-    // check pluginKey validity
-    string::size_type ki = pluginKey.find(':');
-    if (ki == string::npos) {
-        PyErr_SetString(PyExc_TypeError,
-                        "Plugin key must be of the form library:identifier");
-        return "";
-    }
-
-    return pluginKey;
-}
-
-static PyObject *
-getLibraryFor(PyObject *self, PyObject *args)
-{
-    PyObject *pyPluginKey;
-
-    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "getLibraryPathForPlugin() takes plugin key (string) argument");
-        return 0; }
-
-    string pluginKey = toPluginKey(pyPluginKey);
-    if (pluginKey == "") return 0;
-    
-    PluginLoader *loader = PluginLoader::getInstance();
-    string path = loader->getLibraryPathForPlugin(pluginKey);
-    PyObject *pyPath = PyString_FromString(path.c_str());
-    return pyPath;
-}
-
-static PyObject *
-getPluginCategory(PyObject *self, PyObject *args)
-{
-    PyObject *pyPluginKey;
-
-    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "getPluginCategory() takes plugin key (string) argument");
-        return 0; }
-
-    string pluginKey = toPluginKey(pyPluginKey);
-    if (pluginKey == "") return 0;
-
-    PluginLoader *loader = PluginLoader::getInstance();
-    PluginLoader::PluginCategoryHierarchy
-        category = loader->getPluginCategory(pluginKey);
-
-    VectorConversion conv;
-    return conv.PyValue_From_StringVector(category);
-}
-
-static PyObject *
-getOutputList(PyObject *self, PyObject *args)
-{
-    PyObject *pyPluginKey;
-
-    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "getOutputList() takes plugin key (string) argument");
-        return 0; }
-
-    Plugin::OutputList outputs;
-
-    string pluginKey = toPluginKey(pyPluginKey);
-    if (pluginKey == "") return 0;
-
-    PluginLoader *loader = PluginLoader::getInstance();
-
-    Plugin *plugin = loader->loadPlugin(pluginKey, 48000, 0);
-    if (!plugin) {
-        string pyerr("Failed to load plugin: "); pyerr += pluginKey;
-        PyErr_SetString(PyExc_TypeError,pyerr.c_str());
-        return 0;
-    }
-
-    outputs = plugin->getOutputDescriptors();
-
-    PyObject *pyList = PyList_New(outputs.size());
-
-    for (size_t i = 0; i < outputs.size(); ++i) {
-        PyObject *pyOutputId =
-            PyString_FromString(outputs[i].identifier.c_str());
-        PyList_SET_ITEM(pyList, i, pyOutputId);
-    }
-
-    return pyList;
-}
-
-static PyObject *
-loadPlugin(PyObject *self, PyObject *args)
-{
-    PyObject *pyPluginKey;
-    float inputSampleRate;
-    int adapterFlags;
-
-    if (!PyArg_ParseTuple(args, "Sfn",
-                          &pyPluginKey,
-                          &inputSampleRate,
-                          &adapterFlags)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "loadPlugin() takes plugin key (string), sample rate (float), and adapter flags (int) arguments");
-        return 0; }
-
-    string pluginKey = toPluginKey(pyPluginKey);
-    if (pluginKey == "") return 0;
-
-    PluginLoader *loader = PluginLoader::getInstance();
-
-    Plugin *plugin = loader->loadPlugin(pluginKey,
-                                        inputSampleRate,
-                                        adapterFlags);
-    if (!plugin) {
-        string pyerr("Failed to load plugin: "); pyerr += pluginKey;
-        PyErr_SetString(PyExc_TypeError,pyerr.c_str());
-        return 0;
-    }
-
-    return PyPluginObject_From_Plugin(plugin);
-}
-
-// module methods table
-static PyMethodDef vampyhost_methods[] = {
-
-    {"listPlugins", enumeratePlugins, METH_NOARGS,
-     "listPlugins() -> Return a list of the plugin keys of all installed Vamp plugins." },
-
-    {"getPluginPath", getPluginPath, METH_NOARGS,
-     "getPluginPath() -> Return a list of directories which will be searched for Vamp plugins. This may be changed by setting the VAMP_PATH environment variable."},
-
-    {"getCategoryOf", getPluginCategory, METH_VARARGS,
-     "getCategoryOf(pluginKey) -> Return the category of a Vamp plugin given its key, if known. The category is expressed as a list of nested types from least to most specific."},
-
-    {"getLibraryFor", getLibraryFor, METH_VARARGS,
-     "getLibraryFor(pluginKey) -> Return the file path of the Vamp plugin library in which the given plugin key is found, or an empty string if the plugin is not installed."},
-
-    {"getOutputsOf", getOutputList, METH_VARARGS,
-     "getOutputsOf(pluginKey) -> Return a list of the output identifiers of the plugin with the given key, if installed."},
-
-    {"loadPlugin", loadPlugin, METH_VARARGS,
-     "loadPlugin(pluginKey, samplerate) -> Load the plugin that has the given key, if installed, and return the plugin object."},
-
-    {0, 0}              /* sentinel */
-};
-
-PyDoc_STRVAR(module_doc, "Load and run Vamp audio analysis plugins.");
-
-static int
-setint(PyObject *d, const char *name, int value)
-{
-    PyObject *v;
-    int err;
-    v = PyInt_FromLong((long)value);
-    err = PyDict_SetItemString(d, name, v);
-    Py_XDECREF(v);
-    return err;
-}
-
-/* Initialization function for the module (*must* be called initxx) */
-
-// module initialization (includes extern C {...} as necessary)
-PyMODINIT_FUNC
-initvampyhost(void)
-{
-    PyObject *m;
-
-    if (PyType_Ready(&RealTime_Type) < 0) return;
-    if (PyType_Ready(&Plugin_Type) < 0) return;
-
-    m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
-    if (!m) {
-        cerr << "ERROR: initvampyhost: Failed to initialise module" << endl;
-        return;
-    }
-
-    import_array();
-
-    PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type);
-    PyModule_AddObject(m, "Plugin", (PyObject *)&Plugin_Type);
-
-    // Some enum types
-    PyObject *dict = PyModule_GetDict(m);
-    if (!dict) {
-        cerr << "ERROR: initvampyhost: Failed to obtain module dictionary" << endl;
-        return;
-    }
-
-    if (setint(dict, "OneSamplePerStep",
-               Plugin::OutputDescriptor::OneSamplePerStep) < 0 ||
-        setint(dict, "FixedSampleRate",
-               Plugin::OutputDescriptor::FixedSampleRate) < 0 ||
-        setint(dict, "VariableSampleRate",
-               Plugin::OutputDescriptor::VariableSampleRate) < 0 ||
-        setint(dict, "TimeDomain",
-               Plugin::TimeDomain) < 0 ||
-        setint(dict, "FrequencyDomain",
-               Plugin::FrequencyDomain) < 0 ||
-        setint(dict, "AdaptNone",
-               0) < 0 ||
-        setint(dict, "AdaptChannelCount",
-               PluginLoader::ADAPT_CHANNEL_COUNT) < 0 ||
-        setint(dict, "AdaptBufferSize",
-               PluginLoader::ADAPT_BUFFER_SIZE) < 0 ||
-        setint(dict, "AdaptAllSafe",
-               PluginLoader::ADAPT_ALL_SAFE) < 0 ||
-        setint(dict, "AdaptAll",
-               PluginLoader::ADAPT_ALL) < 0) {
-        cerr << "ERROR: initvampyhost: Failed to add enums to module dictionary" << endl;
-        return;
-    }
-}