changeset 0:68f3f32565b4

Import the early draft version
author Chris Cannam
date Mon, 22 Oct 2012 16:10:46 +0100
parents
children cb0d3af1be4d
files Makefile pyRealTime.cpp pyRealTime.h system.h vampyhost-junk.cpp vampyhost.cpp vampyhost.h vampyhost_test.py
diffstat 8 files changed, 1603 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,23 @@
+
+CFLAGS		:= -O2 -Wall -I/usr/include/python2.5 -I/usr/include/vamp-sdk/hostext/ -I/usr/include/vamp-sdk/ -I/Users/Shared/Development/vampy-host-experiments/
+CXXFLAGS	:= -O2 -Wall -I/usr/include/python2.5 -I/usr/include/vamp-sdk/hostext/ -I/usr/include/vamp-sdk/ -I/Users/Shared/Development/vampy-host-experiments/
+LDFLAGS		:= -dynamiclib -lpython2.5 /usr/lib/libvamp-hostsdk.a
+
+
+all: pyRealTime.so vampyhost.so 
+
+pyRealTime.a: pyRealTime.o  
+	ar r $@ pyRealTime.o
+
+pyRealTime.so: pyRealTime.o
+	g++ -shared $^ -o $@ $(LDFLAGS) 
+
+vampyhost.so: vampyhost.o pyRealTime.a
+	g++ -o $@ -shared $^ $(LDFLAGS)
+
+
+clean:	
+	rm *.o
+	rm *.so
+	rm *.a	
+		
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyRealTime.cpp	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,436 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+
+  This module exposes a Type Object wrapping Vamp::RealTime
+  together with module level functions to create 
+  new pyRealTime objects from frame count, samplerate or sec,nsec tuples.
+
+  A small API is provided for the C/C++ programmer and relevant
+  functions are exposed to Python.
+
+  TODO: implement number protocol (i.e. wrap arithmetic operators) 
+  partly done
+
+*/
+
+#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;
+
+/* REAL-TIME TYPE OBJECT */
+
+
+/* Documentation for our new module */
+PyDoc_STRVAR(module_doc,
+             "This module is a thin wrapper around Vamp::RealTime.");
+
+
+/* RealTime Object's Methods */ 
+//Note: 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_toText(RealTimeObject *self, PyObject *args)
+{
+    return Py_BuildValue("s",
+                         self->rt->toText().c_str());
+}
+
+/* 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());
+}
+
+
+/* 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, 
+                        "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);	
+}
+
+/* test */
+static PyObject *
+RealTime_test(PyObject *self)
+{
+
+    long frame = 100;
+    unsigned int sampleRate = 22050;
+	
+    const RealTime t = RealTime::frame2RealTime(frame,sampleRate);
+    long back = RealTime::realTime2Frame(t,sampleRate);
+    cerr << "Reverse Conversion: " << back << endl;
+
+    return Py_BuildValue("s",
+                         ((RealTimeObject*)self)->rt->toString().c_str());
+}
+
+
+/* Type object's (RealTime) methods table */
+static PyMethodDef RealTime_methods[] = {
+
+    {"toText",	(PyCFunction)RealTime_toText,	METH_NOARGS,
+     PyDoc_STR("toText() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
+
+    {"values",	(PyCFunction)RealTime_values,	METH_NOARGS,
+     PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
+
+    {"toFrame",	(PyCFunction)RealTime_toFrame,	METH_VARARGS,
+     PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
+
+    {"toFloat",	(PyCFunction)RealTime_float,	METH_NOARGS,
+     PyDoc_STR("float() -> Floating point representation.")},
+
+    {"test",	(PyCFunction)RealTime_test,	METH_VARARGS,
+     PyDoc_STR("test() -> .")},
+	
+    {NULL,		NULL}		/* sentinel */
+};
+
+
+
+/* Function to set basic attributes */
+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;
+}
+
+/* Function to get basic attributes */
+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);
+}
+
+
+/* DESTRUCTOR: delete type object */
+static void
+RealTimeObject_dealloc(RealTimeObject *self)
+{
+    delete self->rt; 	//delete the C object
+    PyObject_Del(self); //delete the Python object
+}
+
+/*					 Number Protocol 					*/
+
+
+static PyObject *
+RealTime_add(PyObject *s, PyObject *w)
+{
+
+    RealTimeObject *result = 
+        PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (result == NULL) return NULL;
+
+    result->rt = new RealTime::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::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*/
+};
+
+/*					 pyRealTime TypeObject 					*/
+
+
+/* Doc:: 10.3 Type Objects */
+/* static */ PyTypeObject RealTime_Type = {
+    /* The ob_type field must be initialized in the module init function
+     * to be portable to Windows without using C++. */
+    PyObject_HEAD_INIT(NULL)
+    0,						/*ob_size*/
+    "pyRealTime.realtime",				/*tp_name*/
+    sizeof(RealTimeObject),	/*tp_basicsize*/
+    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*/
+    0,                      /*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*/
+    0,                      /*tp_alloc*/
+    0,                      /*tp_new*/
+    0,			            /*tp_free*/
+    0,                      /*tp_is_gc*/
+};
+
+
+/*		 Remaining Functions Exposed by the MODULE 					*/
+
+
+/* New RealTime object from Frame (with given samplerate) */
+/*static*/ PyObject *
+RealTime_frame2RealTime(PyObject *ignored, PyObject *args)
+{
+
+    long frame;
+    unsigned int sampleRate;
+
+    if (!PyArg_ParseTuple(args, "lI:realtime.fame2RealTime ", 
+                          &frame, 
+                          &sampleRate))
+        return NULL;
+    /*Doc:: 5.5 Parsing arguments and building values*/
+
+    RealTimeObject *self;
+    self = PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (self == NULL)
+        return NULL;
+
+    self->rt = new RealTime::RealTime(
+	RealTime::frame2RealTime(frame,sampleRate));
+
+    return (PyObject *) self;
+}
+
+/* New RealTime object from sec and nsec */
+/*static*/ PyObject *
+RealTime_new(PyObject *ignored, PyObject *args)
+{
+
+    unsigned int sec = 0;
+    unsigned int nsec = 0;
+    double unary = 0;
+    const char *fmt = NULL;
+
+    /*Doc:: 5.5 Parsing arguments and building values*/
+    if (
+		
+	!PyArg_ParseTuple(args, "|sd:realtime.new ", 
+                          (const char *) &fmt, 
+                          (double *) &unary) 	&&
+
+	!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); 
+    if (self == NULL) return NULL;
+
+    self->rt = NULL;
+
+    if (sec == 0 && nsec == 0 && fmt == 0) 
+        self->rt = new RealTime::RealTime();
+    else if (fmt == 0)
+        self->rt = new RealTime::RealTime(sec,nsec);
+    else { 
+
+        if (!string(fmt).compare("float") ||
+            !string(fmt).compare("seconds"))  
+            self->rt = new RealTime::RealTime( 
+                RealTime::fromSeconds((double) unary)); 
+
+        if (!string(fmt).compare("milliseconds")) {
+            self->rt = new RealTime::RealTime( 
+                RealTime::fromSeconds((double) unary / 1000.0)); }
+    }
+
+    if (!self->rt) { 
+        PyErr_SetString(PyExc_TypeError, 
+                        "RealTime initialised with wrong arguments.");
+        return NULL; 
+    }
+
+    return (PyObject *) self;
+}
+
+
+/* pyRealTime Module's methods table */
+static PyMethodDef Module_methods[] = {
+
+    {"frame2RealTime",	(PyCFunction)RealTime_frame2RealTime,	METH_VARARGS,
+     PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
+
+    {"realtime",	RealTime_new,		METH_VARARGS,
+     PyDoc_STR("realtime() -> returns new RealTime object")},
+	
+    {NULL,		NULL}		/* sentinel */
+};
+
+
+/*				 PyRealTime C API functions 					*/
+
+
+
+/*RealTime from PyRealTime*/
+RealTime*
+PyRealTime_AsPointer (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; };
+
+/*PyRealTime from RealTime*/
+PyObject* 
+PyRealTime_FromRealTime(Vamp::RealTime *rt) {
+
+    RealTimeObject *self =
+	PyObject_New(RealTimeObject, &RealTime_Type); 
+    if (self == NULL) return NULL;
+
+    self->rt = new RealTime::RealTime(*rt);
+    return (PyObject*) self;
+    //TODO: check if we need to INCREF here
+}
+
+
+/* Module initialization (includes extern "C" {...}) */
+PyMODINIT_FUNC
+initpyRealTime(void)
+{
+    PyObject *m;
+
+    /* Finalize the type object including setting type of the new type
+     * object; doing it here is required for portability to Windows 
+     * without requiring C++. */
+    if (PyType_Ready(&RealTime_Type) < 0)
+        return;
+
+    /* Create the module and add the functions */
+    m = Py_InitModule3("pyRealTime", Module_methods, module_doc);
+    if (m == NULL)
+        return;
+
+//	PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyRealTime.h	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,47 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+#ifndef _PYREALTIME_H_
+#define _PYREALTIME_H_
+
+#include "vamp-sdk/Plugin.h"
+
+/* RealTime Type Object's structure    */
+/* Doc:: 10.2 Common Object Structures */
+typedef struct {
+    PyObject_HEAD
+    /*PyObject	*rt_attrs;*/
+    Vamp::RealTime::RealTime *rt;
+} RealTimeObject; 
+
+PyAPI_DATA(PyTypeObject) RealTime_Type;
+
+#define PyRealTime_CheckExact(v)	((v)->ob_type == &RealTime_Type)
+#define PyRealTime_Check(v) PyObject_TypeCheck(v, &RealTime_Type)
+
+/* pyRealTime C API functions */
+//	Example from Python's stringobject.h
+// 	PyAPI_FUNC(PyObject *) PyString_FromString(const char *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* PyRealTime C API functions */
+	
+PyAPI_FUNC(PyObject *) 
+PyRealTime_FromRealTime(Vamp::RealTime *rt);
+
+PyAPI_FUNC(Vamp::RealTime::RealTime *) 
+PyRealTime_AsPointer (PyObject *self);
+
+/* PyRealTime Module functions */
+
+PyAPI_FUNC(PyObject *)
+RealTime_new(PyObject *ignored, PyObject *args);
+
+PyAPI_FUNC(PyObject *)
+RealTime_frame2RealTime(PyObject *ignored, PyObject *args);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PYREALTIME_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system.h	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,75 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    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 Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _SYSTEM_H_
+#define _SYSTEM_H_
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#define DLOPEN(a,b)  LoadLibrary((a).c_str())
+#define DLSYM(a,b)   GetProcAddress((HINSTANCE)(a),(b))
+#define DLCLOSE(a)   FreeLibrary((HINSTANCE)(a))
+#define DLERROR()    ""
+
+#define PLUGIN_SUFFIX "dll"
+
+#else
+
+#include <dlfcn.h>
+
+#define DLOPEN(a,b)  dlopen((a).c_str(),(b))
+#define DLSYM(a,b)   dlsym((a),(b))
+#define DLCLOSE(a)   dlclose((a))
+#define DLERROR()    dlerror()
+
+#ifdef __APPLE__
+
+#define PLUGIN_SUFFIX  "dylib"
+#define HAVE_OPENDIR 1
+
+#else 
+
+#define PLUGIN_SUFFIX  "so"
+#define HAVE_OPENDIR 1
+
+#endif /* __APPLE__ */
+
+#endif /* ! _WIN32 */
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vampyhost-junk.cpp	Mon Oct 22 16:10:46 2012 +0100
@@ -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/vampyhost.cpp	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,691 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+//include for python extension module: must be first
+#include <Python.h>
+#include <vampyhost.h>
+#include <pyRealTime.h>
+
+//includes for vamp host
+#include "vamp-sdk/Plugin.h"
+#include "vamp-sdk/PluginHostAdapter.h"
+#include "vamp-sdk/hostext/PluginChannelAdapter.h"
+#include "vamp-sdk/hostext/PluginInputDomainAdapter.h"
+#include "vamp-sdk/hostext/PluginLoader.h"
+//#include "vamp/vamp.h"
+
+#include <iostream>
+#include <fstream>
+#include <set>
+#include <sndfile.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <string>
+
+#include "system.h"
+
+#include <cmath>
+
+
+using namespace std;
+using namespace Vamp;
+
+using Vamp::Plugin;
+using Vamp::PluginHostAdapter;
+using Vamp::RealTime;
+using Vamp::HostExt::PluginLoader;
+
+#define HOST_VERSION "1.1"
+
+
+/* MODULE HELPER FUNCTIONS */
+PyDoc_STRVAR(xx_foo_doc, "Some description");
+
+/*obtain C plugin handle and key from pyCobject */
+int getPluginHandle 
+(PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) {
+
+    //char errormsg[]="Wrong input argument: Plugin Handle required.";
+
+    *plugin = NULL;
+    if (!PyCObject_Check(pyPluginHandle)) return NULL;
+
+    //try to convert to Plugin pointer
+    Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle);
+    if (!p) return NULL;	
+
+    string pId;
+
+    if (pKey) {
+	*pKey = (string*) PyCObject_GetDesc(pyPluginHandle);
+	if (!*pKey) return NULL;
+	pId = *(string*) *pKey;
+
+    } else {
+
+	void *pKey = PyCObject_GetDesc(pyPluginHandle);
+	if (!pKey) return NULL;
+	pId = *(string*) pKey;
+    }
+	
+    string::size_type pos = pId.find(':');
+    if (pos == string::npos) return NULL;
+
+    pId = pId.substr(pId.rfind(':')+1);
+    string identifier = p->getIdentifier();	
+			
+    if (pId.compare(identifier)) return NULL;
+
+    *plugin = p;
+    return true;
+}
+
+/*
+  ----------------------------------------------------------------
+*/
+
+
+
+/*
+  VAMPYHOST MAIN 
+  --------------------------------------------------------------------- 
+*/
+
+/* ENUMERATE PLUGINS*/
+
+static PyObject *
+vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
+{
+    string retType;
+	
+    if (!PyArg_ParseTuple(args, "|s:enumeratePlugins", &retType))
+	return NULL;
+
+    //list available plugins
+    PluginLoader *loader = PluginLoader::getInstance();
+    vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
+
+    //library Map
+    typedef multimap<string, PluginLoader::PluginKey> LibraryMap;
+    LibraryMap libraryMap;
+
+    //New list object
+    PyObject *pyList = PyList_New(plugins.size());
+
+    for (size_t i = 0; i < plugins.size(); ++i) {
+        string path = loader->getLibraryPathForPlugin(plugins[i]);
+        libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
+
+	PyObject *pyPluginKey = PyString_FromString(plugins[i].c_str());
+	PyList_SET_ITEM(pyList,i,pyPluginKey);
+		
+    }
+
+    PyList_Sort(pyList);
+    return pyList;
+}
+
+
+/* GET PLUGIN LIBRARY PATH*/
+
+static PyObject *
+vampyhost_getLibraryPath(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+
+    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
+	PyErr_SetString(PyExc_TypeError,
+			"String input argument required: pluginKey");
+	return NULL; }
+
+    //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,
+			"String input argument required: pluginLibrary:Identifier"); 
+       	return NULL;
+    }
+
+    PluginLoader *loader = PluginLoader::getInstance();
+    string path = loader->getLibraryPathForPlugin(pluginKey);
+    PyObject *pyPath = PyString_FromString(path.c_str());
+    return pyPath;
+}
+
+
+/* GET PLUGIN CATEGORY*/
+
+static PyObject *
+vampyhost_getPluginCategory(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+
+    if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
+	PyErr_SetString(PyExc_TypeError,
+			"String input argument required: pluginKey");
+	return NULL; }
+
+    //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,
+			"String input argument required: pluginLibrary:Identifier"); 
+       	return NULL;
+    }
+
+    PluginLoader *loader = PluginLoader::getInstance();
+    PluginLoader::PluginCategoryHierarchy 
+	category = loader->getPluginCategory(pluginKey);
+    string catstring;
+
+    if (!category.empty()) {
+        catstring = "";
+        for (size_t ci = 0; ci < category.size(); ++ci) {
+	    catstring.append(category[ci]);
+            catstring.append(" ");
+        }
+	PyObject *pyCat = PyString_FromString(catstring.c_str());
+	return pyCat;
+    }
+    PyObject *pyCat = PyString_FromString("");
+    return pyCat;
+}
+
+
+
+/* GET PLUGIN OUTPUT LIST*/
+
+static PyObject *
+vampyhost_getOutputList(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginHandle;
+    string pluginKey;
+
+    if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
+	PyErr_SetString(PyExc_TypeError,
+			"Invalid argument: plugin handle or plugin key required.");
+	return NULL; 
+    }
+
+    //check if we have a plugin key string or a handle object
+    if (PyString_Check(pyPluginHandle) ) {
+
+	pluginKey.assign(PyString_AS_STRING(pyPluginHandle));
+	//check pluginKey Validity
+    	string::size_type ki = pluginKey.find(':');
+    	if (ki == string::npos) {
+	    PyErr_SetString(PyExc_TypeError,
+			    "String input argument required: pluginLibrary:Identifier"); 
+	    return NULL;
+    	}
+
+    } else {
+		
+	string *key;	
+	Plugin *plugin; 
+
+	if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
+	    PyErr_SetString(PyExc_TypeError,
+			    "Invalid or deleted plugin handle.");
+	    return NULL; }
+	pluginKey.assign(*key);
+    } 
+	
+    //This code creates new instance of the plugin anyway
+    PluginLoader *loader = PluginLoader::getInstance();
+	
+    //load plugin
+    Plugin *plugin = loader->loadPlugin (pluginKey, 48000);
+    if (!plugin) { 		
+	string pyerr("Failed to load plugin: "); pyerr += pluginKey;
+	PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 
+	return NULL;
+    }		
+
+    Plugin::OutputList outputs = plugin->getOutputDescriptors();
+    //Plugin::OutputDescriptor od;
+
+    if (outputs.size()<1) {
+	string pyerr("Plugin has no output: "); pyerr += pluginKey;
+	PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 
+	return NULL;
+    }
+
+    //New list object
+    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);		
+    }
+
+    delete plugin;
+    return pyList;
+}
+
+
+
+/* LOAD PLUGIN */
+
+static PyObject *
+vampyhost_loadPlugin(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginKey;
+    float inputSampleRate;
+
+    if (!PyArg_ParseTuple(args, "Sf", 
+			  &pyPluginKey,
+			  &inputSampleRate)) {
+	PyErr_SetString(PyExc_TypeError,
+			"String input argument required: pluginKey");
+	return NULL; }
+
+    //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,
+			"String input argument required: pluginLibrary:Identifier"); 
+       	return NULL;
+    }
+
+    PluginLoader *loader = PluginLoader::getInstance();
+	
+    //load plugin
+    Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate);
+    if (!plugin) { 		
+	string pyerr("Failed to load plugin: "); pyerr += pluginKey;
+	PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 
+	return NULL;
+    }		
+    //void *identifier = (void*) new string(pluginKey);
+    PyPluginDescriptor *pd = new PyPluginDescriptor;
+	
+    pd->key = pluginKey;
+    pd->isInitialised = false;
+    pd->inputSampleRate = inputSampleRate;
+	
+    //New PyCObject
+    //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc( 
+    //(void*) plugin, identifier, NULL);	
+
+    PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc( 
+	(void*) plugin, (void*) pd, NULL);	
+		
+    return pyPluginHandle;
+}
+
+
+
+/* UNLOAD PLUGIN */
+
+static PyObject *
+vampyhost_unloadPlugin(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginHandle;
+
+    if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
+	PyErr_SetString(PyExc_TypeError,
+			"Wrong input argument: Plugin Handle required.");
+	return NULL; }
+
+    string *key;	
+    Plugin *plugin; 
+
+    if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
+	PyErr_SetString(PyExc_TypeError,
+			"Invalid or already deleted plugin handle.");
+	return NULL; }
+
+/*	Prevent repeated calls from causing segfault
+	sice it will fail type checking the 2nd time:						*/
+    PyCObject_SetVoidPtr(pyPluginHandle,NULL);
+	
+    PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
+	
+    delete plugin;
+    delete pd;
+    return pyPluginHandle;
+
+}
+
+
+/* INITIALISE PLUGIN */
+
+static PyObject *
+vampyhost_initialise(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginHandle;
+    size_t channels,blockSize,stepSize;
+    //PyObject pyInputSampleType;
+    bool mixChannels = false;
+
+    if (!PyArg_ParseTuple (args, "Oiii",  &pyPluginHandle, 
+			   (size_t) &channels, 
+			   (size_t) &stepSize, 
+			   (size_t) &blockSize)) 
+    {
+	PyErr_SetString(PyExc_TypeError,
+			"Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
+	return NULL; 
+    }
+
+    Plugin *plugin; 
+    string *key; 
+
+    if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
+	PyErr_SetString(PyExc_TypeError,
+			"Invalid plugin handle.");
+	return NULL; }
+
+    // here we cast the void pointer as PyPluginDescriptor instead of string
+    PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;	
+
+    plugDesc->channels = channels;
+    plugDesc->stepSize = stepSize;
+    plugDesc->blockSize = blockSize;
+    plugDesc->inputSampleType = PyPluginDescriptor::int16;
+    plugDesc->sampleSize = 2;
+    plugDesc->mixChannels = mixChannels; 
+	
+    size_t minch = plugin->getMinChannelCount();
+    size_t maxch = plugin->getMaxChannelCount();
+    if (mixChannels) channels = 1;
+
+    /* TODO: DO WE WANT TO MIX IT DOWN? */
+    if (maxch < channels || channels < minch) {
+	PyErr_SetString(PyExc_TypeError,
+			"Invalid number of channels.");
+	return NULL; }
+
+    if (!plugin->initialise(channels, stepSize, blockSize)) {
+	PyErr_SetString(PyExc_TypeError,
+			"Plugin initialization failed.");
+	return NULL; }
+
+    plugDesc->identifier = 
+	plugDesc->key.substr(plugDesc->key.rfind(':')+1);
+    plugDesc->isInitialised = true;
+	
+    return Py_True;
+}
+
+
+/* RUN PROCESS */
+
+static PyObject *
+vampyhost_process(PyObject *self, PyObject *args)
+{
+    PyObject *pyPluginHandle;
+    PyObject *pyBuffer;
+    PyObject *pyRealTime;
+
+    if (!PyArg_ParseTuple(args, "OOO", 
+			  &pyPluginHandle,	// C object holding a pointer to a plugin and its descriptor
+			  &pyBuffer,			// Audio data
+			  &pyRealTime)) {		// TimeStamp
+	PyErr_SetString(PyExc_TypeError,
+			"Required: plugin handle, buffer, timestmap.");
+	return NULL; }
+
+    if (!PyRealTime_Check(pyRealTime)) {
+	PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
+	return NULL; }
+
+    // RealTime *rt = PyRealTime_AsPointer(pyRealTime);
+    // if (!rt) return NULL;
+    // cerr << ">>>sec: " << rt->sec << " nsec: " << rt->nsec << endl;
+    // 
+    // PyObject *rrt = PyRealTime_FromRealTime (rt);
+
+    string *key;	
+    Plugin *plugin; 
+
+    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 sample_size = sizeof(short);
+
+    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; }
+    short *input = 
+	reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
+
+    //convert int16 PCM data to 32-bit floats
+    float **plugbuf = new float*[channels];
+    float normfact = 1.0f / 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) {
+	    plugbuf[c][j] = normfact *
+		static_cast <float> (input[j * channels + c]);
+	    ++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);
+
+    // long frame = 1;
+    // unsigned int samplerate = (unsigned int) pd->inputSampleRate;
+
+    RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime);
+
+    //Call process and store the output
+    pd->output = plugin->process(
+	plugbuf, 
+	timeStamp);
+
+    /* TODO:  DO SOMETHONG WITH THE FEATURE SET HERE */
+/// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
+
+
+    //We can safely delete here
+    for(size_t k=0; k<channels; k++){
+	delete[] plugbuf[k];
+    }
+    delete[] plugbuf;
+
+    return pyReturnBuffer;
+
+}
+
+/* GET / SET OUTPUT */
+
+//getOutput(plugin,outputNo)
+static PyObject *
+vampyhost_getOutput(PyObject *self, PyObject *args) {
+
+    PyObject *pyPluginHandle;
+//	PyObject *pyBuffer;
+//	PyObject *pyRealTime;
+    PyObject *pyOutput;
+
+    if (!PyArg_ParseTuple(args, "OO", 
+			  &pyPluginHandle,	// C object holding a pointer to a plugin and its descriptor
+			  &pyOutput)) {		// Output reference
+	PyErr_SetString(PyExc_TypeError,
+			"Required: plugin handle, buffer, timestmap.");
+	return NULL; }
+
+    string *key;	
+    Plugin *plugin; 
+
+    if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
+	PyErr_SetString(PyExc_AttributeError,
+			"Invalid or already deleted plugin handle.");
+	return NULL; }
+
+    PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
+
+    unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
+
+    //Get output list: but we don't need it
+    //Plugin::FeatureList features = pd->output[outputNo];
+
+    size_t outLength = pd->output[outputNo].size();
+
+    //New PyList for the featurelist
+    PyObject *pyFeatureList = PyList_New(outLength);
+
+    for (size_t i = 0; i < outLength; ++i) {
+	// Test:
+	/*
+	  XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type); 
+	  if (pyFeature == NULL) break; //return NULL;
+
+	  pyFeature->x_attr = NULL;
+	  pyFeature->feature = &pd->output[outputNo][i];
+
+	  PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);		
+	*/
+    }
+
+    Py_INCREF(pyFeatureList);
+    return pyFeatureList;
+
+// EXPLAIN WHAT WE NEED TO DO HERE:
+// We have the block output in pd->output
+// FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v	
+// Vamp::Plugin::FeatureSet output; = pd->output	
+// typedef std::vector<Feature> FeatureList;
+// typedef std::map<int, FeatureList> FeatureSet; // key is output no
+
+    // 	THIS IS FOR OUTPUT id LOOKUP LATER 
+    //     Plugin::OutputList outputs = plugin->getOutputDescriptors();
+    // 
+    // if (outputs.size()<1) {
+    // 	string pyerr("Plugin has no output: "); pyerr += pluginKey;
+    // 	PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 
+    // 	return NULL;
+    // }
+    // 
+    // //New list object
+    // 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);		
+    //     }
+	
+}
+
+
+
+
+/* List of functions defined in this module */
+//module methods table
+static PyMethodDef vampyhost_methods[] = {
+
+    {"enumeratePlugins",	vampyhost_enumeratePlugins,	METH_VARARGS,
+     xx_foo_doc},
+
+    {"getLibraryPath",	vampyhost_getLibraryPath, METH_VARARGS,
+     xx_foo_doc},
+
+    {"getPluginCategory",	vampyhost_getPluginCategory, METH_VARARGS,
+     xx_foo_doc},
+
+    {"getOutputList",	vampyhost_getOutputList, METH_VARARGS,
+     xx_foo_doc},
+
+    {"loadPlugin",	vampyhost_loadPlugin, METH_VARARGS,
+     xx_foo_doc},
+
+    {"process",	vampyhost_process, METH_VARARGS,
+     xx_foo_doc},
+
+    {"unloadPlugin",	vampyhost_unloadPlugin, METH_VARARGS,
+     xx_foo_doc},
+
+    {"initialise",	vampyhost_initialise, METH_VARARGS,
+     xx_foo_doc},
+
+    {"getOutput",	vampyhost_getOutput, METH_VARARGS,
+     xx_foo_doc},
+
+    /* Add RealTime Module Methods */
+
+    {"frame2RealTime",	(PyCFunction)RealTime_frame2RealTime,	METH_VARARGS,
+     PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
+
+    {"realtime",	(PyCFunction)RealTime_new,		METH_VARARGS,
+     PyDoc_STR("realtime() -> returns new RealTime object")},
+			
+    {NULL,		NULL}		/* sentinel */
+};
+
+//Documentation for our new module
+PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
+
+/* Initialization function for the module (*must* be called initxx) */
+
+//module initialization (includes extern C {...} as necessary)
+PyMODINIT_FUNC
+initvampyhost(void)
+{
+    PyObject *m;
+
+    /* Finalize the type object including setting type of the new type
+     * object; doing it here is required for portability to Windows 
+     * without requiring C++. */
+
+    if (PyType_Ready(&RealTime_Type) < 0)
+	return;
+//	PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
+
+    /* Create the module and add the functions */
+    m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
+    if (m == NULL) return;
+
+    // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vampyhost.h	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,43 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef _VAMPYHOST_H_
+#define _VAMPYHOST_H_
+
+#include "vamp-sdk/Plugin.h"
+#include <string>
+
+// structure of NumPy array intrface (just a hack, shouldn't be needed here...)
+typedef struct {
+    int two;              /* contains the integer 2 -- simple sanity check */
+    int nd;               /* number of dimensions */
+    char typekind;        /* kind in array --- character code of typestr */
+    int itemsize;         /* size of each element */
+    int flags;            /* flags indicating how the data should be interpreted */
+                          /*   must set ARR_HAS_DESCR bit to validate descr */
+    Py_intptr_t *shape;   /* A length-nd array of shape information */
+    Py_intptr_t *strides; /* A length-nd array of stride information */
+    void *data;           /* A pointer to the first element of the array */
+    PyObject *descr;      /* NULL or data-description (same as descr key */
+                          /*        of __array_interface__) -- must set ARR_HAS_DESCR */
+                          /*        flag or this will be ignored. */
+} PyArrayInterface;
+
+//structure for holding plugin instance data
+typedef struct {
+    std::string key;
+    std::string identifier;
+    bool isInitialised;
+    float inputSampleRate;
+    size_t channels;
+    size_t blockSize;
+    size_t stepSize;
+    size_t sampleSize;
+    bool mixChannels;
+    enum InputSampleType {
+	int16,
+	float32 }; 
+    InputSampleType inputSampleType;
+    Vamp::Plugin::FeatureSet output;
+} PyPluginDescriptor;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vampyhost_test.py	Mon Oct 22 16:10:46 2012 +0100
@@ -0,0 +1,118 @@
+
+import sys
+sys.path.append('/Users/Shared/Development/python-extensions')
+sys.path.append('/Users/Shared/Development/vampy-host-experiments/')
+#from melscale import melscale
+#from melscale import initialize
+import wave 
+from wave import *
+from pylab import *
+# from melscale import *
+from numpy import *
+from pylab import *
+from time import *
+
+from vampyhost import *
+import vampyhost 
+import vampyhost as vh
+#import pyRealTime
+#from pyRealTime import *
+
+
+#deal with an audio file
+wavfile='/Users/Shared/multitrack (small)/mix.wav'
+
+wavobj = wave.open(wavfile,'r')
+samplerate = wavobj.getframerate()
+print "samplerate: ",samplerate
+print "number of samples (frames): ",wavobj.getnframes() #total number of samples 4647744
+channels = wavobj.getnchannels();
+print "channels: ",channels 
+print "sample-width: ",wavobj.getsampwidth() 
+print "position: ",wavobj.tell()
+wavobj.setpos(1000000)
+
+print wavobj.tell()
+audio = wavobj.readframes(1024) #returns an 8-bit buffer
+print wavobj.tell()
+print dir(audio)
+print len(audio)
+wavobj.close()
+
+
+
+rt=realtime(4,70)
+
+#test RealTime Object
+for i in [0,1,2] :
+	if (i==0) : rtl=[]
+	rtl.append(realtime())
+	print ">>>>>RealTime's method: ", rtl[i].values()
+
+
+class feature_example():
+	def __init__(self):
+		self.hasTimestamp
+		self.timestamp
+		self.values
+		self.label
+		
+pluginlist = vh.enumeratePlugins()
+for i,n in enumerate(pluginlist) : print i,":",n
+pluginKey=pluginlist[12];
+
+retval = vh.getLibraryPath(pluginKey)
+print pluginKey
+print retval
+
+print vh.getPluginCategory(pluginKey)
+print vh.getOutputList(pluginKey)
+handle = vh.loadPlugin(pluginKey,samplerate);
+print "\n\nPlugin handle: ",handle
+
+print "Output list of: ",pluginKey,"\n",vh.getOutputList(handle)
+
+#initialise: pluginhandle, channels, stepSize, blockSize
+vh.initialise(handle,1,1024,1024)
+
+rt=frame2RealTime(100000,22050)
+print type(rt)
+
+out=vh.process(handle,audio,rt)
+output = vh.getOutput(handle,1);
+
+print type(output)
+print output
+#print output[1].label
+
+print "_______________OUTPUT TYPE_________:",type(out)
+in_audio = frombuffer(audio,int16,-1,0) 
+out_audio = frombuffer(out,float32,-1,0)
+subplot(211)
+plot(in_audio)
+subplot(212)
+plot(out_audio)
+
+show()
+#do some processing here
+
+#buffer is a multichannel frame or a numpy array containing samples
+#buffer = vh.frame(audiodata,stepSize,blockSize)
+
+#output = vh.process(handle,buffer)
+
+#output is a list of list of features
+
+vh.unloadPlugin(handle);
+vh.unloadPlugin(handle); # test if it chrashes... 
+
+print vh.getOutputList(handle)
+
+#cases:
+#buffer = blockSize : evaluate
+#buffer > blockSize : enframe and zeropad
+#return:
+#oneSamplePerStep, FixedSamplerate : can return numpy array
+#variableSamplerate : list of featres only
+
+#print dir(vampyhost)	
\ No newline at end of file