changeset 26:014c48d6f360

Now we know what we want from Vampy source, bring it in here again and lose the subrepo
author Chris Cannam
date Wed, 26 Nov 2014 09:48:35 +0000
parents 5379af6bef00
children fb6519598734
files .hgsub .hgsubstate Makefile PyRealTime.cpp PyRealTime.h PyTypeConversions.cpp PyTypeConversions.h vampyhost.cpp vampyhost.h
diffstat 9 files changed, 1531 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsub	Wed Nov 26 09:38:56 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-vampy = https://code.soundsoftware.ac.uk/hg/vampy
--- a/.hgsubstate	Wed Nov 26 09:38:56 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-2a9fb03458d74565845654aff6a0f2b8dc677248 vampy
--- a/Makefile	Wed Nov 26 09:38:56 2014 +0000
+++ b/Makefile	Wed Nov 26 09:48:35 2014 +0000
@@ -2,12 +2,12 @@
 PY_INCLUDE_PATH	:= /usr/include/python2.7
 NUMPY_INCLUDE_PATH := /usr/lib/python2.7/site-packages/numpy/core/include
 
-CFLAGS		:= -DHAVE_NUMPY -D_VAMP_PLUGIN_IN_HOST_NAMESPACE=1 -g -fPIC -Wall -Werror -Ivampy -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
-CXXFLAGS	:= -DHAVE_NUMPY -D_VAMP_PLUGIN_IN_HOST_NAMESPACE=1 -g -fPIC -Wall -Werror -Ivampy -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
+CFLAGS		:= -DHAVE_NUMPY -g -fPIC -Wall -Werror -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
+CXXFLAGS	:= -DHAVE_NUMPY -g -fPIC -Wall -Werror -I$(PY_INCLUDE_PATH) -I$(NUMPY_INCLUDE_PATH) -I.
 
 LDFLAGS		:= -shared -Wl,-Bstatic -lvamp-hostsdk -Wl,-Bdynamic -Wl,-z,defs -lpython2.7 -ldl
 
-OBJECTS	:= vampy/PyRealTime.o vampy/PyFeature.o vampy/PyFeatureSet.o vampy/PyTypeConversions.o vampyhost.o
+OBJECTS	:= PyRealTime.o PyTypeConversions.o vampyhost.o
 
 all: vampyhost.so
 
@@ -15,4 +15,4 @@
 	g++ -o $@ -shared $^ $(LDFLAGS)
 
 clean:	
-	rm -f vampy/*.o *.o *.so *.a
+	rm -f *.o *.so *.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PyRealTime.cpp	Wed Nov 26 09:48:35 2014 +0000
@@ -0,0 +1,366 @@
+/* -*- 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 "PyRealTime.h"
+#include "vamp-sdk/Plugin.h"
+#include <string>
+
+using namespace std;
+using namespace Vamp;
+using Vamp::Plugin;
+using Vamp::RealTime;
+
+/* 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,//sizeof(RealTime),		/*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,//(ternaryfunc)RealTime_new,                      /*tp_call*/
+    0,                      /*tp_str*/
+    0,                      /*tp_getattro*/
+    0,                      /*tp_setattro*/
+    0,                      /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,     /*tp_flags*/
+    "RealTime Object",      /*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/PyRealTime.h	Wed Nov 26 09:48:35 2014 +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/PyTypeConversions.cpp	Wed Nov 26 09:48:35 2014 +0000
@@ -0,0 +1,866 @@
+/* -*- 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 "PyTypeConversions.h"
+
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX ((size_t) -1)
+#endif
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+/*  Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
+	(EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
+
+PyTypeConversions::PyTypeConversions() : 
+	m_strict(false),
+	m_error(false),
+	m_numpyInstalled(false),
+	error(m_error) // const public reference for easy access
+{
+}
+
+PyTypeConversions::~PyTypeConversions()
+{
+}
+
+/// floating point numbers (TODO: check numpy.float128)
+float 
+PyTypeConversions::PyValue_To_Float(PyObject* pyValue) const
+{
+	// convert float
+	if (pyValue && PyFloat_Check(pyValue)) 
+		//TODO: check for limits here (same on most systems)
+		return (float) PyFloat_AS_DOUBLE(pyValue);
+	
+	if (pyValue == NULL)
+	{
+		setValueError("Error while converting object " + PyValue_Get_TypeName(pyValue) + " to float. ",m_strict);
+		return 0.0;		
+	}
+		
+	// in strict mode we will not try harder
+	if (m_strict) {
+		setValueError("Strict conversion error: object" + PyValue_Get_TypeName(pyValue) +" is not float.",m_strict);
+		return 0.0;
+	}
+
+	// convert other objects supporting the number protocol
+	if (PyNumber_Check(pyValue))
+	{
+		PyObject* pyFloat = PyNumber_Float(pyValue); // new ref
+		if (!pyFloat)
+		{
+			if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+			setValueError("Error while converting " + PyValue_Get_TypeName(pyValue) + " object to float.",m_strict);
+			return 0.0;
+		}
+		float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
+		Py_DECREF(pyFloat);
+		return rValue;
+	}
+/*	
+	// convert other objects supporting the number protocol
+	if (PyNumber_Check(pyValue)) 
+	{	
+		// PEP353: Py_ssize_t is size_t but signed !
+		// This will work up to numpy.float64
+		Py_ssize_t rValue = PyNumber_AsSsize_t(pyValue,NULL);
+		if (PyErr_Occurred()) 
+		{
+			PyErr_Print(); PyErr_Clear();
+			setValueError("Error while converting integer object.",m_strict);
+			return 0.0;
+		}
+		if (rValue > (Py_ssize_t)FLT_MAX || rValue < (Py_ssize_t)FLT_MIN)
+		{
+			setValueError("Overflow error. Object can not be converted to float.",m_strict);
+			return 0.0;
+		}
+		return (float) rValue;
+	}
+*/	
+    // convert string
+	if (PyString_Check(pyValue))
+	{
+		PyObject* pyFloat = PyFloat_FromString(pyValue,NULL);
+		if (!pyFloat) 
+		{
+			if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+			setValueError("String value can not be converted to float.",m_strict);
+			return 0.0;
+		}
+		float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
+		if (PyErr_Occurred()) 
+		{
+			PyErr_Print(); PyErr_Clear(); 
+			Py_CLEAR(pyFloat);
+			setValueError("Error while converting float object.",m_strict);
+			return 0.0;
+		}
+		Py_DECREF(pyFloat);
+		return rValue;
+	}
+	
+	// convert the first element of any iterable sequence (for convenience and backwards compatibility)
+	if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0) 
+	{
+		PyObject* item = PySequence_GetItem(pyValue,0);
+		if (item)
+		{
+			float rValue = this->PyValue_To_Float(item);
+			if (!m_error) {
+				Py_DECREF(item);
+				return rValue;
+			} else {
+				Py_CLEAR(item);
+				std::string msg = "Could not convert sequence element to float. ";
+				setValueError(msg,m_strict);
+				return 0.0;
+			}
+		}
+	}
+
+    // give up
+	if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+	std::string msg = "Conversion from " + PyValue_Get_TypeName(pyValue) + " to float is not possible.";
+	setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_Float failed. " << msg << endl;
+#endif	
+	return 0.0;
+}
+
+/// size_t (unsigned integer types)
+size_t 
+PyTypeConversions::PyValue_To_Size_t(PyObject* pyValue) const
+{
+	// convert objects supporting the number protocol 
+	if (PyNumber_Check(pyValue)) 
+	{	
+		if (m_strict && !PyInt_Check(pyValue) && !PyLong_Check(pyValue)) 
+			setValueError("Strict conversion error: object is not integer type.",m_strict);
+		// Note: this function handles Bool,Int,Long,Float
+		// speed is not critical in the use of this type by Vamp
+		// PEP353: Py_ssize_t is size_t but signed ! 
+		Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
+		if (PyErr_Occurred()) 
+		{
+			PyErr_Print(); PyErr_Clear();
+			setValueError("Error while converting integer object.",m_strict);
+			return 0;
+		}
+		// this test is nonsense -- neither part can occur
+		// owing to range of data types -- size_t is at least
+		// as big as long, and unsigned is always non-negative
+/*
+		if ((unsigned long)rValue > SIZE_T_MAX || (unsigned long)rValue < 0)
+		{
+			setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
+			return 0;
+		}
+*/
+		return (size_t) rValue;
+	}
+	
+	// in strict mode we will not try harder and throw an exception
+	// then the caller should decide what to do with it
+	if (m_strict) {
+		setValueError("Strict conversion error: object is not integer.",m_strict);
+		return 0;
+	}
+	
+	// convert string
+	if (PyString_Check(pyValue))
+	{
+		PyObject* pyLong = PyNumber_Long(pyValue);
+		if (!pyLong) 
+		{
+			if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+			setValueError("String object can not be converted to size_t.",m_strict);
+			return 0;
+		}
+		size_t rValue = this->PyValue_To_Size_t(pyLong);
+		if (!m_error) {
+			Py_DECREF(pyLong);
+			return rValue;
+		} else {
+			Py_CLEAR(pyLong);
+			setValueError ("Error converting string to size_t.",m_strict);
+			return 0;
+		}
+	}
+	
+	// convert the first element of iterable sequences
+	if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0) 
+	{
+		PyObject* item = PySequence_GetItem(pyValue,0);
+		if (item)
+		{
+			size_t rValue = this->PyValue_To_Size_t(item);
+			if (!m_error) {
+				Py_DECREF(item);
+				return rValue;
+			} else {
+				Py_CLEAR(item);
+				setValueError("Could not convert sequence element to size_t. ",m_strict);
+				return 0;
+			}
+		}
+	}
+	
+    // give up
+	if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+	std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to size_t is not possible.";
+	setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_Size_t failed. " << msg << endl;
+#endif	
+	return 0;
+}
+
+/// long and int
+long 
+PyTypeConversions::PyValue_To_Long(PyObject* pyValue) const
+{
+	// most common case: convert int (faster)
+	if (pyValue && PyInt_Check(pyValue)) {
+		// if the object is not NULL and verified, this macro just extracts the value.
+		return PyInt_AS_LONG(pyValue);
+	} 
+	
+	// long
+	if (PyLong_Check(pyValue)) {
+		long rValue = PyLong_AsLong(pyValue);
+		if (PyErr_Occurred()) { 
+			PyErr_Print(); PyErr_Clear(); 
+			setValueError("Error while converting long object.",m_strict);
+			return 0;
+		}
+		return rValue;
+	}
+	
+	if (m_strict) {
+		setValueError("Strict conversion error: object is not integer or long integer.",m_strict);
+		return 0;
+	}
+	
+	// convert all objects supporting the number protocol
+	if (PyNumber_Check(pyValue)) 
+	{	
+		// Note: this function handles Bool,Int,Long,Float
+		// PEP353: Py_ssize_t is size_t but signed ! 
+		Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
+		if (PyErr_Occurred()) 
+		{
+			PyErr_Print(); PyErr_Clear();
+			setValueError("Error while converting integer object.",m_strict);
+			return 0;
+		}
+		if (rValue > LONG_MAX || rValue < LONG_MIN)
+		{
+			setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
+			return 0;
+		}
+		return (long) rValue;
+	}
+	
+	// convert string
+	if (PyString_Check(pyValue))
+	{
+		PyObject* pyLong = PyNumber_Long(pyValue);
+		if (!pyLong) 
+		{
+			if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+			setValueError("String object can not be converted to long.",m_strict);
+			return 0;
+		}
+		long rValue = this->PyValue_To_Long(pyLong);
+		if (!m_error) {
+			Py_DECREF(pyLong);
+			return rValue;
+		} else {
+			Py_CLEAR(pyLong);
+			setValueError ("Error converting string to long.",m_strict);
+			return 0;
+		}
+	}
+	
+	// convert the first element of iterable sequences
+	if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0) 
+	{
+		PyObject* item = PySequence_GetItem(pyValue,0);
+		if (item)
+		{
+			size_t rValue = this->PyValue_To_Long(item);
+			if (!m_error) {
+				Py_DECREF(item);
+				return rValue;
+			} else {
+				Py_CLEAR(item);
+				setValueError("Could not convert sequence element to long. ",m_strict);
+				return 0;
+			}
+		}
+	}
+	
+    // give up
+	if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+	std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to long is not possible.";
+	setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_Long failed. " << msg << endl;
+#endif	
+	return 0;
+}
+
+
+bool 
+PyTypeConversions::PyValue_To_Bool(PyObject* pyValue) const
+{
+	// convert objects supporting the number protocol
+	// Note: PyBool is a subclass of PyInt
+	if (PyNumber_Check(pyValue)) 
+	{	
+		if (m_strict && !PyBool_Check(pyValue)) 
+			setValueError
+			("Strict conversion error: object is not boolean type.",m_strict);
+
+		// Note: this function handles Bool,Int,Long,Float
+		Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
+		if (PyErr_Occurred()) 
+		{
+			PyErr_Print(); PyErr_Clear();
+			setValueError ("Error while converting boolean object.",m_strict);
+		}
+		if (rValue != 1 && rValue != 0)
+		{
+			setValueError ("Overflow error. Object can not be converted to boolean.",m_strict);
+		}
+		return (bool) rValue;
+	}
+	
+	if (m_strict) {
+		setValueError ("Strict conversion error: object is not numerical type.",m_strict);
+		return false;
+	}
+	
+	// convert iterables: the rule is the same as in the interpreter:
+	// empty sequence evaluates to False, anything else is True
+	if (PySequence_Check(pyValue)) 
+	{
+		return PySequence_Size(pyValue)?true:false;
+	}
+	
+    // give up
+	if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
+	std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to boolean is not possible.";
+	setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_Bool failed. " << msg << endl;
+#endif	
+	return false;
+}
+
+/// string and objects that support .__str__() 
+/// TODO: check unicode objects
+std::string 
+PyTypeConversions::PyValue_To_String(PyObject* pyValue) const
+{
+	// convert string
+	if (PyString_Check(pyValue)) 
+	{	
+		char *cstr = PyString_AS_STRING(pyValue);
+		if (!cstr) 
+		{
+			if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+			setValueError("Error while converting string object.",m_strict);
+			return std::string();
+		}
+		return std::string(cstr);
+	}
+	// TODO: deal with unicode here (argh!)
+	
+	// in strict mode we will not try harder
+	if (m_strict) {
+		setValueError("Strict conversion error: object is not string.",m_strict);
+		return std::string();
+	}
+	
+	// accept None as empty string
+	if (pyValue == Py_None) return std::string();
+			
+	// convert list or tuple: empties are turned into empty strings conventionally
+	if (PyList_Check(pyValue) || PyTuple_Check(pyValue)) 
+	{
+		if (!PySequence_Size(pyValue)) return std::string();
+		PyObject* item = PySequence_GetItem(pyValue,0);
+		if (item)
+		{
+			std::string rValue = this->PyValue_To_String(item);
+			if (!m_error) {
+				Py_DECREF(item);
+				return rValue;
+			} else {
+				Py_CLEAR(item);
+				setValueError("Could not convert sequence element to string.",m_strict);
+				return std::string();
+			}
+		}
+	}
+
+	// convert any other object that has .__str__() or .__repr__()
+	PyObject* pyString = PyObject_Str(pyValue);
+	if (pyString && !PyErr_Occurred())
+	{
+		std::string rValue = this->PyValue_To_String(pyString);
+		if (!m_error) {
+			Py_DECREF(pyString);
+			return rValue;
+		} else {
+			Py_CLEAR(pyString);
+			std::string msg = "Object " + this->PyValue_Get_TypeName(pyValue) +" can not be represented as string. ";
+			setValueError (msg,m_strict);
+			return std::string();
+		}
+	}
+
+	// give up
+	PyErr_Print(); PyErr_Clear();
+	std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to string is not possible.";
+	setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_String failed. " << msg << endl;
+#endif	
+	return std::string();
+}
+
+/*			 			C Values to Py Values				  		*/
+
+
+PyObject*
+PyTypeConversions::PyValue_From_CValue(const char* cValue) const
+{
+	// returns new reference
+#ifdef _DEBUG
+	if (!cValue) {
+		std::string msg = "PyTypeConversions::PyValue_From_CValue: Null pointer encountered while converting from const char* .";
+		cerr << msg << endl;
+		setValueError(msg,m_strict);
+		return NULL;
+	}
+#endif
+	PyObject *pyValue = PyString_FromString(cValue);
+	if (!pyValue)
+	{
+		if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+		setValueError("Error while converting from char* or string.",m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from const char*" << endl;
+#endif
+		return NULL;
+	}
+	return pyValue;
+}
+
+PyObject*
+PyTypeConversions::PyValue_From_CValue(size_t cValue) const
+{
+	// returns new reference
+	PyObject *pyValue = PyInt_FromSsize_t((Py_ssize_t)cValue);
+	if (!pyValue)
+	{
+		if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+		setValueError("Error while converting from size_t.",m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from size_t" << endl;
+#endif
+		return NULL;
+	}
+	return pyValue;
+}
+
+PyObject*
+PyTypeConversions::PyValue_From_CValue(double cValue) const
+{
+	// returns new reference
+	PyObject *pyValue = PyFloat_FromDouble(cValue);
+	if (!pyValue)
+	{
+		if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+		setValueError("Error while converting from float or double.",m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from float or double" << endl;
+#endif
+		return NULL;
+	}
+	return pyValue;
+}
+
+PyObject*
+PyTypeConversions::PyValue_From_CValue(bool cValue) const
+{
+	// returns new reference
+	PyObject *pyValue = PyBool_FromLong((long)cValue);
+	if (!pyValue)
+	{
+		if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+		setValueError("Error while converting from bool.",m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyValue_From_CValue: Interpreter failed to convert from bool" << endl;
+#endif
+		return NULL;
+	}
+	return pyValue;
+}
+
+
+/*			 			Sequence Types to C++ Types	    		  	*/
+
+//convert Python list to C++ vector of strings
+std::vector<std::string> 
+PyTypeConversions::PyValue_To_StringVector (PyObject *pyList) const 
+{
+	
+	std::vector<std::string> Output;
+	std::string ListElement;
+	PyObject *pyString = NULL;
+	
+	if (PyList_Check(pyList)) {
+
+		for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
+			//Get next list item (Borrowed Reference)
+			pyString = PyList_GET_ITEM(pyList,i);
+			ListElement = (string) PyString_AsString(PyObject_Str(pyString));
+			Output.push_back(ListElement);
+		}
+		return Output;
+	}
+
+// #ifdef _DEBUG
+// 	cerr << "PyTypeConversions::PyValue_To_StringVector: Warning: Value is not list of strings." << endl;
+// #endif
+
+	/// Assume a single value that can be casted as string 
+	/// this allows to write e.g. Feature.label = 5.2 instead of ['5.2']
+	Output.push_back(PyValue_To_String(pyList));
+	if (m_error) {
+		std::string msg = "Value is not list of strings nor can be casted as string. ";
+		setValueError(msg,m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyValue_To_StringVector failed. " << msg << endl;
+#endif
+	}
+	return Output;
+}
+
+//convert PyFeature.value (typically a list or numpy array) to C++ vector of floats
+std::vector<float> 
+PyTypeConversions::PyValue_To_FloatVector (PyObject *pyValue) const 
+{
+
+#ifdef HAVE_NUMPY
+if (m_numpyInstalled) 
+{
+	// there are four types of values we may receive from a numpy process:
+	// * a python scalar, 
+	// * an array scalar, (e.g. numpy.float32)
+	// * an array with nd = 0  (0D array)
+	// * an array with nd > 0
+
+	/// check for scalars
+	if (PyArray_CheckScalar(pyValue) || PyFloat_Check(pyValue)) {
+
+		std::vector<float> Output;
+
+		// we rely on the behaviour the scalars are either floats
+		// or support the number protocol
+		// TODO: a potential optimisation is to handle them directly
+		Output.push_back(PyValue_To_Float(pyValue));
+		return Output;
+	}
+
+	/// numpy array
+	if (PyArray_CheckExact(pyValue)) 
+		return PyArray_To_FloatVector(pyValue);
+}
+#endif
+
+	/// python list of floats (backward compatible)
+	if (PyList_Check(pyValue)) {
+		return PyList_To_FloatVector(pyValue);
+	}
+
+	std::vector<float> Output;
+	
+	/// finally assume a single value supporting the number protocol 
+	/// this allows to write e.g. Feature.values = 5 instead of [5.00]
+	Output.push_back(PyValue_To_Float(pyValue));
+	if (m_error) {
+		std::string msg = "Value is not list or array of floats nor can be casted as float. ";
+		setValueError(msg,m_strict);
+#ifdef _DEBUG
+	cerr << "PyTypeConversions::PyValue_To_FloatVector failed. " << msg << endl;
+#endif
+	}
+	return Output;
+}
+
+//convert a list of python floats
+std::vector<float> 
+PyTypeConversions::PyList_To_FloatVector (PyObject *inputList) const 
+{
+	std::vector<float> Output;
+	
+#ifdef _DEBUG
+	// This is a low level function normally called from 
+	// PyValue_To_FloatVector(). Checking for list is not required.
+	if (!PyList_Check(inputList)) {
+		std::string msg = "Value is not list.";
+		setValueError(msg,true);
+		cerr << "PyTypeConversions::PyList_To_FloatVector failed. " << msg << endl;
+		return Output; 
+	} 
+#endif
+
+	float ListElement;
+	PyObject *pyFloat = NULL;
+	PyObject **pyObjectArray = PySequence_Fast_ITEMS(inputList);
+
+	for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
+
+		// pyFloat = PyList_GET_ITEM(inputList,i);
+		pyFloat = pyObjectArray[i];
+
+#ifdef _DEBUG
+		if (!pyFloat) {
+			if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+			cerr << "PyTypeConversions::PyList_To_FloatVector: Could not obtain list element: " 
+			<< i << " PyList_GetItem returned NULL! Skipping value." << endl;
+			continue;
+		}
+#endif		
+
+		// ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
+		ListElement = PyValue_To_Float(pyFloat);
+		
+
+#ifdef _DEBUG_VALUES
+		cerr << "value: " << ListElement << endl;
+#endif
+		Output.push_back(ListElement);
+	}
+	return Output;
+}
+
+// if numpy is not installed this will not be called, 
+// therefor we do not check again
+#ifdef HAVE_NUMPY 
+std::vector<float> 
+PyTypeConversions::PyArray_To_FloatVector (PyObject *pyValue) const 
+{
+	std::vector<float> Output;
+	
+#ifdef _DEBUG
+	// This is a low level function, normally called from 
+	// PyValue_To_FloatVector(). Checking the array here is not required.
+	if (!PyArray_Check(pyValue)) {
+		std::string msg = "Object has no array conversions.";
+		setValueError(msg,true);
+		cerr << "PyTypeConversions::PyArray_To_FloatVector failed. " << msg << endl;
+		return Output; 
+	} 
+#endif
+
+	PyArrayObject* pyArray = (PyArrayObject*) pyValue;
+	PyArray_Descr* descr = PyArray_DESCR(pyArray);
+	
+	/// check raw data and descriptor pointers
+	if (PyArray_DATA(pyArray) == 0 || descr == 0) {
+		std::string msg = "NumPy array with NULL data or descriptor pointer encountered.";
+		setValueError(msg,m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << endl;
+#endif		
+		return Output;
+	}
+
+	/// check dimensions
+	if (PyArray_NDIM(pyArray) != 1) {
+		std::string msg = "NumPy array must be a one dimensional vector.";
+		setValueError(msg,m_strict);
+#ifdef _DEBUG
+		cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << " Dims: " << (int) PyArray_NDIM(pyArray) << endl;
+#endif	
+		return Output;
+	}
+
+#ifdef _DEBUG_VALUES
+	cerr << "PyTypeConversions::PyArray_To_FloatVector: Numpy array verified." << endl;
+#endif
+	
+	/// 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 :
+			std::string msg = "Unsupported value type in NumPy array object.";
+			setValueError(msg,m_strict);
+#ifdef _DEBUG
+			cerr << "PyTypeConversions::PyArray_To_FloatVector failed. Error: " << msg << endl;
+#endif			
+			return Output;
+	}
+}
+
+PyObject *
+PyTypeConversions::FloatVector_To_PyArray(const vector<float> &v) const
+{
+	npy_intp ndims[1];
+	ndims[0] = (int)v.size();
+	PyObject *arr = PyArray_SimpleNew(1, ndims, dtype_float32);
+	float *data = (float *)PyArray_DATA((PyArrayObject *)arr);
+	for (int i = 0; i < ndims[0]; ++i) {
+		data[i] = v[i];
+	}
+	return arr;
+}
+#endif
+
+PyObject *
+PyTypeConversions::PyValue_From_StringVector(const std::vector<std::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
+PyTypeConversions::setValueError (std::string message, bool strict) const
+{
+	m_error = true;
+	m_errorQueue.push(ValueError(message,strict));
+}
+
+/// return a reference to the last error or creates a new one.
+ValueError&
+PyTypeConversions::lastError() const 
+{
+	m_error = false;
+	if (!m_errorQueue.empty()) return m_errorQueue.back();
+	else {
+		m_errorQueue.push(ValueError("Type conversion error.",m_strict));
+		return m_errorQueue.back();
+	}
+}
+
+/// helper function to iterate over the error message queue:
+/// pops the oldest item
+ValueError 
+PyTypeConversions::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
+std::string
+PyTypeConversions::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 std::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 std::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 std::string("< unknown type >");
+	}
+	Py_DECREF(pyType);
+	Py_DECREF(pyString);
+	return std::string(cstr);
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PyTypeConversions.h	Wed Nov 26 09:48:35 2014 +0000
@@ -0,0 +1,198 @@
+/* -*- 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.
+*/
+
+/*
+    PyTypeConversions: Type safe conversion utilities between Python
+    types and basic C/C++ types.
+*/
+
+#ifndef PY_TYPE_CONVERSIONS_H
+#define PY_TYPE_CONVERSIONS_H
+
+#include <Python.h>
+
+#ifdef HAVE_NUMPY
+#define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
+#define NO_IMPORT_ARRAY
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include "numpy/arrayobject.h"
+#endif
+
+#include <vector>
+#include <queue>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+using std::cerr;
+using std::endl;
+
+#ifdef HAVE_NUMPY
+enum eArrayDataType {
+	dtype_float32 = (int) NPY_FLOAT,
+	dtype_complex64 = (int) NPY_CFLOAT 
+	};
+#endif 
+
+/* C++ mapping of PyNone Type */
+struct NoneType {};
+	
+// Data
+class ValueError
+{
+public:
+	ValueError() {}
+	ValueError(std::string m, bool s) : message(m),strict(s) {}
+	std::string location;
+	std::string message;
+	bool strict;
+	std::string str() const { 
+		return (location.empty()) ? message : message + "\nLocation: " + location;}
+	void print() const { cerr << str() << endl; }
+	template<typename V> ValueError &operator<< (const V& v)
+	{
+		std::ostringstream ss;
+		ss << v;
+		location += ss.str();
+		return *this;
+	}
+};
+
+class PyTypeConversions
+{
+public:
+	PyTypeConversions();
+	~PyTypeConversions();
+	
+	// Utilities
+	void setStrictTypingFlag(bool b) {m_strict = b;}
+	void setNumpyInstalled(bool b) {m_numpyInstalled = b;}
+	ValueError getError() const;
+	std::string PyValue_Get_TypeName(PyObject*) const;
+
+	// Basic type conversion: Python to C++ 
+	float 	PyValue_To_Float(PyObject*) const;
+	size_t 	PyValue_To_Size_t(PyObject*) const;
+	bool 	PyValue_To_Bool(PyObject*) const;
+	std::string PyValue_To_String(PyObject*) const;
+	long 	PyValue_To_Long(PyObject*) const;
+	// int 	PyValue_To_Int(PyObject* pyValue) const;
+	
+	// C++ to Python
+	PyObject *PyValue_From_CValue(const char*) const;
+	PyObject *PyValue_From_CValue(const std::string& x) const { return PyValue_From_CValue(x.c_str()); }
+	PyObject *PyValue_From_CValue(size_t) const;
+	PyObject *PyValue_From_CValue(double) const;
+	PyObject *PyValue_From_CValue(float x) const { return PyValue_From_CValue((double)x); }
+	PyObject *PyValue_From_CValue(bool) const;
+	
+	// Sequence types
+	std::vector<std::string> PyValue_To_StringVector (PyObject*) const;
+	std::vector<float> PyValue_To_FloatVector (PyObject*) const;
+	std::vector<float> PyList_To_FloatVector (PyObject*) const;
+
+	PyObject *PyValue_From_StringVector(const std::vector<std::string> &) const;
+	
+	// Numpy types
+#ifdef HAVE_NUMPY
+	std::vector<float> PyArray_To_FloatVector (PyObject *pyValue) const;
+	PyObject *FloatVector_To_PyArray(const std::vector<float> &) const; // Copying the data
+#endif
+
+	/// Convert DTYPE type 1D NumpyArray to std::vector<RET>
+	template<typename RET, typename DTYPE>
+	std::vector<RET> PyArray_Convert(void* raw_data_ptr, long length, size_t strides) const
+	{
+		std::vector<RET> rValue;
+		
+		/// 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 (long i = 0; i<length; ++i){
+				rValue.push_back((RET)(*((DTYPE*)data)));
+#ifdef _DEBUG_VALUES
+				cerr << "value: " << (RET)(*((DTYPE*)data)) << endl;
+#endif				
+				data+=strides;
+			}
+			return rValue;
+		}
+
+		DTYPE* data = (DTYPE*) raw_data_ptr;
+		for (long i = 0; i<length; ++i){
+#ifdef _DEBUG_VALUES
+			cerr << "value: " << (RET)data[i] << endl;
+#endif
+			rValue.push_back((RET)data[i]);
+		}
+		return rValue;
+	}
+
+	/// this is a special case. numpy.float64 has an array conversions but no array descriptor
+	std::vector<float> PyArray0D_Convert(PyArrayInterface *ai) const
+	{
+		std::vector<float> rValue;
+		if ((ai->typekind) == *"f") 
+			rValue.push_back((float)*(double*)(ai->data));
+		else { 
+			setValueError("Unsupported NumPy data type.",m_strict); 
+			return rValue;
+		}
+#ifdef _DEBUG_VALUES
+		cerr << "value: " << rValue[0] << endl;
+#endif
+		return rValue;
+	}
+
+private:
+	bool m_strict;
+	mutable bool m_error;
+	mutable std::queue<ValueError> m_errorQueue;
+	bool m_numpyInstalled;
+	
+	void setValueError(std::string,bool) const;
+	ValueError& lastError() const;
+
+public:
+	const bool& error;
+
+};
+
+#endif
--- a/vampyhost.cpp	Wed Nov 26 09:38:56 2014 +0000
+++ b/vampyhost.cpp	Wed Nov 26 09:48:35 2014 +0000
@@ -1,5 +1,42 @@
 /* -*- 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 for python extension module: must be first
 #include <Python.h>
 
--- a/vampyhost.h	Wed Nov 26 09:38:56 2014 +0000
+++ b/vampyhost.h	Wed Nov 26 09:48:35 2014 +0000
@@ -1,6 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-#ifndef _VAMPYHOST_H_
-#define _VAMPYHOST_H_
-
-#endif