changeset 6:e1b508f2f914

Added support to memory buffers to be used with NumPy (and some rationalisation of code)
author fazekasgy
date Wed, 19 Mar 2008 16:02:29 +0000
parents 6ed5ebd38fde
children a4c955e9a70b
files Example VamPy plugins/PyZeroCrossing.py Makefile Mutex.cpp PyPlugin.cpp PyPlugin.h pyvamp-main.cpp
diffstat 6 files changed, 259 insertions(+), 425 deletions(-) [+]
line wrap: on
line diff
--- a/Example VamPy plugins/PyZeroCrossing.py	Fri Mar 14 12:09:34 2008 +0000
+++ b/Example VamPy plugins/PyZeroCrossing.py	Wed Mar 19 16:02:29 2008 +0000
@@ -7,7 +7,7 @@
 class PyZeroCrossing: 
 	
 	def __init__(self): 
-		self.m_imputSampleRate = 44100 
+		self.m_imputSampleRate = 0.0 
 		self.m_stepSize = 0
 		self.m_blockSize = 0
 		self.m_channels = 0
@@ -38,7 +38,7 @@
 			
 	def getOutputDescriptors(self):
 		
-		#descriptors are python dictionary
+		#descriptors are python dictionaries
 		output0={
 		'identifier':'vampy-counts',
 		'name':'Number of Zero Crossings',
@@ -131,7 +131,7 @@
 			self.previousSample = prev
 		else :
 			count = 0.0
-			self.previousSample = inbuf[len(inbuf)-2]
+			self.previousSample = inbuf[len(inbuf)-1]
 
 		feature0={
 		'hasTimestamp':False,		
--- a/Makefile	Fri Mar 14 12:09:34 2008 +0000
+++ b/Makefile	Wed Mar 19 16:02:29 2008 +0000
@@ -1,289 +1,26 @@
 
-# Makefile for the Vamp plugin SDK.  This builds the SDK objects,
-# libraries, example plugins, and the test host.  Please adjust to
-# suit your operating system requirements.
+CXXFLAGS	:= -I../vamp-plugin-sdk -O2 -Wall -I/usr/include/python2.5
 
-APIDIR		= sdk/vamp
-SDKDIR		= sdk/vamp-sdk
-HOSTEXTDIR	= sdk/vamp-sdk/hostext
-#EXAMPLEDIR	= sdk/examples
-HOSTDIR		= sdk/host
-EXAMPLEDIR	= .
+vampy.dylib:	PyPlugin.o PyPlugScanner.o pyvamp-main.o Mutex.o
+	g++ -shared $^ -o $@ -L../vamp-plugin-sdk/vamp-sdk -lvamp-sdk -dynamiclib -lpython2.5 -lpthread
 
-###
-### Start of user-serviceable parts
-###
+clean:	
+	rm *.o
 
-# Default build target (or use "make <target>" to select one).
-# Targets are:
-#   all       -- build everything
-#   sdk       -- build all the Vamp SDK libraries for plugins and hosts
-#   sdkstatic -- build only the static versions of the SDK libraries
-#   plugins   -- build the example plugins (and the SDK if required)
-#   host      -- build the simple Vamp plugin host (and the SDK if required)
-#   test      -- build the host and example plugins, and run a quick test
-#   _clean    -- remove binary targets
-#   distclean -- remove all targets
-#	cleanplug -- remove compiled plugin files
 
-default:	plugins
-
-# Compile flags
+# Install plugin
 #
-CXXFLAGS	:= $(CXXFLAGS) -O2 -Wall -I. -fPIC 
-
-# ar, ranlib
-#
-AR			:= ar
-RANLIB		:= ranlib
-
-# Libraries required for the plugins.
-# (Note that it is desirable to statically link libstdc++ if possible,
-# because our plugin exposes only a C API so there are no boundary
-# compatibility problems.)
-#
-PLUGIN_LIBS	= $(SDKDIR)/libvamp-sdk.a
-#PLUGIN_LIBS	= $(SDKDIR)/libvamp-sdk.a $(shell g++ -print-file-name=libstdc++.a)
-
-# File extension for a dynamically loadable object
-#
-#PLUGIN_EXT	= .so
-#PLUGIN_EXT	= .dll
-PLUGIN_EXT	= .dylib
-
-# Libraries required for the host.
-#
-HOST_LIBS	= $(SDKDIR)/libvamp-hostsdk.a -lsndfile -ldl
-
-# Locations for "make install".  This will need quite a bit of 
-# editing for non-Linux platforms.  Of course you don't necessarily
-# have to use "make install".
-#
-INSTALL_PREFIX	  		:= /usr/local
-INSTALL_API_HEADERS	  	:= $(INSTALL_PREFIX)/include/vamp
-INSTALL_SDK_HEADERS	  	:= $(INSTALL_PREFIX)/include/vamp-sdk
-INSTALL_HOSTEXT_HEADERS	:= $(INSTALL_PREFIX)/include/vamp-sdk/hostext
-INSTALL_SDK_LIBS		:= $(INSTALL_PREFIX)/lib
-
-INSTALL_SDK_LIBNAME			:= libvamp-sdk.dylib.1.1.0
-INSTALL_SDK_LINK_ABI	  	:= libvamp-sdk.dylib.1
-INSTALL_SDK_LINK_DEV	  	:= libvamp-sdk.dylib
-INSTALL_SDK_STATIC        	:= libvamp-sdk.o
-INSTALL_SDK_LA            	:= libvamp-sdk.la
-
-INSTALL_HOSTSDK_LIBNAME   	:= libvamp-hostsdk.dylib.2.0.0
-INSTALL_HOSTSDK_LINK_ABI  	:= libvamp-hostsdk.dylib.2
-INSTALL_HOSTSDK_LINK_DEV  	:= libvamp-hostsdk.dylib
-INSTALL_HOSTSDK_STATIC    	:= libvamp-hostsdk.a
-INSTALL_HOSTSDK_LA        	:= libvamp-hostsdk.la
-
-INSTALL_PKGCONFIG		  	:= $(INSTALL_PREFIX)/lib/pkgconfig
-
-# Install plugins to this location
-#
-LIBRARY_PREFIX				:=/Library
-INSTALL_PLUGIN				:=$(LIBRARY_PREFIX)/Audio/Plug-Ins/Vamp
-
-# Flags required to tell the compiler to create a dynamically loadable object
-#
-#DYNAMIC_LDFLAGS		= --static-libgcc -shared -Wl,-Bsymbolic
-DYNAMIC_LDFLAGS		= -dynamiclib 
-PLUGIN_LDFLAGS		= $(DYNAMIC_LDFLAGS)
-SDK_DYNAMIC_LDFLAGS	= $(DYNAMIC_LDFLAGS) -Wl,-soname=$(INSTALL_SDK_LINK_ABI)
-HOSTSDK_DYNAMIC_LDFLAGS	= $(DYNAMIC_LDFLAGS) -Wl,-soname=$(INSTALL_HOSTSDK_LINK_ABI)
-
-## For OS/X with g++:
-#DYNAMIC_LDFLAGS			= -dynamiclib
-PLUGIN_LDFLAGS				= $(DYNAMIC_LDFLAGS) 
-SDK_DYNAMIC_LDFLAGS			= $(DYNAMIC_LDFLAGS)
-HOSTSDK_DYNAMIC_LDFLAGS		= $(DYNAMIC_LDFLAGS)
-
-
-### End of user-serviceable parts
-
-# Plugin headers, compiler objects and targets
-
-PLUGIN_HEADERS	= \
-		$(EXAMPLEDIR)/PyPlugScanner.h \
-		$(EXAMPLEDIR)/PyPlugin.h
-
-PLUGIN_OBJECTS	= \
-		$(EXAMPLEDIR)/PyPlugScanner.o \
-		$(EXAMPLEDIR)/PyPlugin.o \
-		$(EXAMPLEDIR)/pyvamp-main.o
-
-PLUGIN_NAME = vamp-pyvamp-plugin
-
-PLUGIN_TARGET	= \
-		$(EXAMPLEDIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-
-PLUGIN_DESCRIPTORS	= \
-		$(EXAMPLEDIR)/exampleplugin.n3 
-
-# We need to link with python
-# Links the actual python executable. forces to export symbol _PyMac_Error
-PYTHON_LINK_AS_SHARED := \
-		-u _PyMac_Error /Library/Frameworks/Python.framework/Versions/2.5/Python
-
-API_HEADERS	= \
-		$(APIDIR)/vamp.h
-
-SDK_HEADERS	= \
-		$(SDKDIR)/Plugin.h \
-		$(SDKDIR)/PluginAdapter.h \
-		$(SDKDIR)/PluginBase.h \
-		$(SDKDIR)/RealTime.h
-
-HOSTSDK_HEADERS	= \
-		$(SDKDIR)/Plugin.h \
-		$(SDKDIR)/PluginBase.h \
-		$(SDKDIR)/PluginHostAdapter.h \
-		$(SDKDIR)/RealTime.h
-
-HOSTEXT_HEADERS = \
-		$(HOSTEXTDIR)/PluginBufferingAdapter.h \
-		$(HOSTEXTDIR)/PluginChannelAdapter.h \
-		$(HOSTEXTDIR)/PluginInputDomainAdapter.h \
-		$(HOSTEXTDIR)/PluginLoader.h \
-		$(HOSTEXTDIR)/PluginWrapper.h
-
-SDK_OBJECTS	= \
-		$(SDKDIR)/PluginAdapter.o \
-		$(SDKDIR)/RealTime.o
-
-HOSTSDK_OBJECTS	= \
-		$(SDKDIR)/PluginHostAdapter.o \
-		$(HOSTEXTDIR)/PluginBufferingAdapter.o \
-		$(HOSTEXTDIR)/PluginChannelAdapter.o \
-		$(HOSTEXTDIR)/PluginInputDomainAdapter.o \
-		$(HOSTEXTDIR)/PluginLoader.o \
-		$(HOSTEXTDIR)/PluginWrapper.o \
-		$(SDKDIR)/RealTime.o
-
-SDK_STATIC	= \
-		$(SDKDIR)/libvamp-sdk.a
-
-HOSTSDK_STATIC	= \
-		$(SDKDIR)/libvamp-hostsdk.a
-
-SDK_DYNAMIC	= \
-		$(SDKDIR)/libvamp-sdk$(PLUGIN_EXT)
-
-HOSTSDK_DYNAMIC	= \
-		$(SDKDIR)/libvamp-hostsdk$(PLUGIN_EXT)
-
-SDK_LA		= \
-		$(SDKDIR)/libvamp-sdk.la
-
-HOSTSDK_LA	= \
-		$(SDKDIR)/libvamp-hostsdk.la
-
-HOST_HEADERS	= \
-		$(HOSTDIR)/system.h
-
-HOST_OBJECTS	= \
-		$(HOSTDIR)/vamp-simple-host.o
-
-HOST_TARGET	= \
-		$(HOSTDIR)/vamp-simple-host
-
-#Primary Make rules
-#
-
-sdk:	sdkstatic $(SDK_DYNAMIC) $(HOSTSDK_DYNAMIC)
-
-sdkstatic:	
-		$(SDK_STATIC) $(HOSTSDK_STATIC)
-		$(RANLIB) $(SDK_STATIC)
-		$(RANLIB) $(HOSTSDK_STATIC)
-
-plugins:	$(PLUGIN_TARGET)
-
-host:		$(HOST_TARGET)
-
-all:		sdk plugins host test
-
-#This is where all the stuff gets built
-#
-
-$(SDK_STATIC):	$(SDK_OBJECTS) $(API_HEADERS) $(SDK_HEADERS)
-		$(AR) r $@ $(SDK_OBJECTS)
-
-$(HOSTSDK_STATIC):	$(HOSTSDK_OBJECTS) $(API_HEADERS) $(HOSTSDK_HEADERS) $(HOSTEXT_HEADERS)
-		$(AR) r $@ $(HOSTSDK_OBJECTS)
-
-$(SDK_DYNAMIC):	$(SDK_OBJECTS) $(API_HEADERS) $(SDK_HEADERS)
-		$(CXX) $(LDFLAGS) $(SDK_DYNAMIC_LDFLAGS) -o $@ $(SDK_OBJECTS)
-
-$(HOSTSDK_DYNAMIC):	$(HOSTSDK_OBJECTS) $(API_HEADERS) $(HOSTSDK_HEADERS) $(HOSTEXT_HEADERS)
-		$(CXX) $(LDFLAGS) $(HOSTSDK_DYNAMIC_LDFLAGS) -o $@ $(HOSTSDK_OBJECTS)
-
-$(PLUGIN_TARGET):	$(PLUGIN_OBJECTS) $(SDK_STATIC) $(PLUGIN_HEADERS)
-		$(CXX) $(LDFLAGS) $(PLUGIN_LDFLAGS) -o $@ $(PLUGIN_OBJECTS) $(PLUGIN_LIBS) $(PYTHON_LINK_AS_SHARED)
-
-$(HOST_TARGET):	$(HOST_OBJECTS) $(HOSTSDK_STATIC) $(HOST_HEADERS)
-		$(CXX) $(LDFLAGS) $(HOST_LDFLAGS) -o $@ $(HOST_OBJECTS) $(HOST_LIBS)
-
-test:		plugins host
-		VAMP_PATH=$(EXAMPLEDIR) $(HOST_TARGET) -l
-
-_clean:		
-		rm -f $(SDK_OBJECTS) $(HOSTSDK_OBJECTS) $(PLUGIN_OBJECTS) $(HOST_OBJECTS)
-
-cleanplug : 	
-		rm -f $(PLUGIN_OBJECTS) 
-		rm -f $(EXAMPLEDIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-#		rm -f $(LIBRARY_PREFIX)/$(INSTALL_PLUGIN)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-
-
-distclean:	clean
-		rm -f $(SDK_STATIC) $(SDK_DYNAMIC) $(HOSTSDK_STATIC) $(HOSTSDK_DYNAMIC) $(PLUGIN_TARGET) $(HOST_TARGET) *~ */*~
-
-_install:	$(SDK_STATIC) $(SDK_DYNAMIC) $(HOSTSDK_STATIC) $(HOSTSDK_DYNAMIC) $(PLUGIN_TARGET) $(HOST_TARGET)
-		mkdir -p $(DESTDIR)$(INSTALL_API_HEADERS)
-		mkdir -p $(DESTDIR)$(INSTALL_SDK_HEADERS)
-		mkdir -p $(DESTDIR)$(INSTALL_HOSTEXT_HEADERS)
-		mkdir -p $(DESTDIR)$(INSTALL_SDK_LIBS)
-		mkdir -p $(DESTDIR)$(INSTALL_PKGCONFIG)
-		cp $(API_HEADERS) $(DESTDIR)$(INSTALL_API_HEADERS)
-		cp $(SDK_HEADERS) $(DESTDIR)$(INSTALL_SDK_HEADERS)
-		cp $(HOSTSDK_HEADERS) $(DESTDIR)$(INSTALL_SDK_HEADERS)
-		cp $(HOSTEXT_HEADERS) $(DESTDIR)$(INSTALL_HOSTEXT_HEADERS)
-		cp $(SDK_STATIC) $(DESTDIR)$(INSTALL_SDK_LIBS)
-		cp $(HOSTSDK_STATIC) $(DESTDIR)$(INSTALL_SDK_LIBS)
-		cp $(SDK_DYNAMIC) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LIBNAME)
-		cp $(HOSTSDK_DYNAMIC) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LIBNAME)
-		rm -f $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_ABI)
-		ln -s $(INSTALL_SDK_LIBNAME) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_ABI)
-		rm -f $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_ABI)
-		ln -s $(INSTALL_HOSTSDK_LIBNAME) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_ABI)
-		rm -f $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_DEV)
-		ln -s $(INSTALL_SDK_LIBNAME) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_DEV)
-		rm -f $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_DEV)
-		ln -s $(INSTALL_HOSTSDK_LIBNAME) $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_DEV)
-		sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(APIDIR)/vamp.pc.in \
-		> $(DESTDIR)$(INSTALL_PKGCONFIG)/vamp.pc
-		sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(SDKDIR)/vamp-sdk.pc.in \
-		> $(DESTDIR)$(INSTALL_PKGCONFIG)/vamp-sdk.pc
-		sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(SDKDIR)/vamp-hostsdk.pc.in \
-		> $(DESTDIR)$(INSTALL_PKGCONFIG)/vamp-hostsdk.pc
-		sed -e "s,%LIBNAME%,$(INSTALL_SDK_LIBNAME),g" \
-		    -e "s,%LINK_ABI%,$(INSTALL_SDK_LINK_ABI),g" \
-		    -e "s,%LINK_DEV%,$(INSTALL_SDK_LINK_DEV),g" \
-		    -e "s,%STATIC%,$(INSTALL_SDK_STATIC),g" \
-		    -e "s,%LIBS%,$(INSTALL_SDK_LIBS),g" $(SDK_LA).in \
-		> $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LA)
-		sed -e "s,%LIBNAME%,$(INSTALL_HOSTSDK_LIBNAME),g" \
-		    -e "s,%LINK_ABI%,$(INSTALL_HOSTSDK_LINK_ABI),g" \
-		    -e "s,%LINK_DEV%,$(INSTALL_HOSTSDK_LINK_DEV),g" \
-		    -e "s,%STATIC%,$(INSTALL_HOSTSDK_STATIC),g" \
-		    -e "s,%LIBS%,$(INSTALL_SDK_LIBS),g" $(HOSTSDK_LA).in \
-		> $(DESTDIR)$(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LA)
-
-installplug:
-			mkdir -p $(INSTALL_PLUGIN)
-			rm -f $(INSTALL_PLUGIN)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-			cp $(PLUGIN_NAME)$(PLUGIN_EXT) $(INSTALL_PLUGIN)/$(PLUGIN_NAME)$(PLUGIN_EXT)
-#			cp $(PLUGIN_DESCRIPTORS) $(INSTALL_PLUGIN)
-
-installplugin: installplug
+LIBRARY_PREFIX		:=/Library
+INSTALL_DIR			:=$(LIBRARY_PREFIX)/Audio/Plug-Ins/Vamp
+PYEXAMPLE_DIR		:='Example VamPy Plugins'
+PLUGIN_NAME			:=vampy
+PLUGIN_EXT			:=.dylib
+	
+install:
+	mkdir -p $(INSTALL_DIR)
+	rm -f $(INSTALL_DIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)
+	cp $(PLUGIN_NAME)$(PLUGIN_EXT) $(INSTALL_DIR)/$(PLUGIN_NAME)$(PLUGIN_EXT)	
+	cp $(PYEXAMPLE_DIR)/*.py $(INSTALL_DIR)
+	
+installplug : install
+cleanplug : clean
--- a/Mutex.cpp	Fri Mar 14 12:09:34 2008 +0000
+++ b/Mutex.cpp	Wed Mar 19 16:02:29 2008 +0000
@@ -6,7 +6,6 @@
 */
 
 #include "Mutex.h"
-
 #include <iostream>
 
 #ifndef _WIN32
--- a/PyPlugin.cpp	Fri Mar 14 12:09:34 2008 +0000
+++ b/PyPlugin.cpp	Wed Mar 19 16:02:29 2008 +0000
@@ -57,7 +57,7 @@
 #define pathsep ('/')
 #endif
 
-#define _DEBUG
+//#define _DEBUG
 
 using std::string;
 using std::vector;
@@ -72,109 +72,30 @@
 static std::map<std::string, p::eParmDescriptors> parmKeys;
 
 Mutex PyPlugin::m_pythonInterpreterMutex;
-
-void initMaps()
-{
-	outKeys["identifier"] = identifier;
-	outKeys["name"] = name;
-	outKeys["description"] = description;
-	outKeys["unit"] = unit;
-	outKeys["hasFixedBinCount"] = hasFixedBinCount; 
-	outKeys["binCount"] = binCount;
-	outKeys["binNames"] = binNames;
-	outKeys["hasKnownExtents"] = hasKnownExtents;
-	outKeys["minValue"] = minValue;
-	outKeys["maxValue"] = maxValue;
-	outKeys["isQuantized"] = isQuantized;
-	outKeys["quantizeStep"] = quantizeStep;
-	outKeys["sampleType"] = sampleType;
-	outKeys["sampleRate"] = sampleRate;
-
-	sampleKeys["OneSamplePerStep"] = OneSamplePerStep;
-	sampleKeys["FixedSampleRate"] = FixedSampleRate;
-	sampleKeys["VariableSampleRate"] = VariableSampleRate;
-
-	ffKeys["hasTimestamp"] = hasTimestamp;
-	ffKeys["timeStamp"] = timeStamp;
-	ffKeys["values"] = values;
-	ffKeys["label"] = label;
-
-	parmKeys["identifier"] = p::identifier;
-	parmKeys["name"] = p::name;
-	parmKeys["description"] = p::description;
-	parmKeys["unit"] = p::unit;
-	parmKeys["minValue"] = p::minValue;
-	parmKeys["maxValue"] = p::maxValue;
-	parmKeys["defaultValue"] = p::defaultValue;
-	parmKeys["isQuantized"] = p::isQuantized;
-
-}
-
-
-//missing API helper: convert Python list to C++ vector of strings
-//TODO: these could be templates if we need more of this kind
-std::vector<std::string> PyList_To_StringVector (PyObject *inputList) {
-	
-	std::vector<std::string> Output;
-	std::string ListElement;
-	PyObject *pyString = NULL;
-	
-	if (!PyList_Check(inputList)) return Output;
-
-	for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
-		//Get next list item (Borrowed Reference)
-		pyString = PyList_GET_ITEM(inputList,i);
-		ListElement = (string) PyString_AsString(PyObject_Str(pyString));
-		Output.push_back(ListElement);
-	}
-	return Output;
-}
-
-//missing API helper: convert Python list to C++ vector of floats
-std::vector<float> PyList_As_FloatVector (PyObject *inputList) {
-	
-	std::vector<float> Output;
-	float ListElement;
-	PyObject *pyFloat = NULL;
-	
-	if (!PyList_Check(inputList)) return Output; 
-
-	for (Py_ssize_t k = 0; k < PyList_GET_SIZE(inputList); ++k) {
-		//Get next list item (Borrowed Reference)
-		pyFloat =  PyList_GET_ITEM(inputList,k);
-		ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
-		Output.push_back(ListElement);
-	}
-
-	return Output;
-}
-
-/* TODO: find out why this produces error, also 
-		do sg more clever about handling RealTime
-Vamp::RealTime 
-PyFrame_As_RealTime (PyObject *frameNo,size_t inputSampleRate) {
-Vamp::RealTime result =  
-Vamp::RealTime::frame2RealTime((size_t)PyInt_AS_LONG(frameNo), inputSampleRate);
-return result;
-}
-*/
-
+static bool isMapInitialised = false;
 
 PyPlugin::PyPlugin(std::string pluginKey,float inputSampleRate, PyObject *pyInstance) :
     Plugin(inputSampleRate),
 	m_pyInstance(pyInstance),
 	m_stepSize(0),
-    m_previousSample(0.0f),
+	m_blockSize(0),
+    m_channels(0),
 	m_plugin(pluginKey),
 	m_class(pluginKey.substr(pluginKey.rfind(':')+1,pluginKey.size()-1)),
-	m_path((pluginKey.substr(0,pluginKey.rfind(pathsep))))
+	m_path((pluginKey.substr(0,pluginKey.rfind(pathsep)))),
+	m_processType(0),
+	m_pyProcess(NULL),
+	m_inputDomain(TimeDomain)
 {	
 }
 
 PyPlugin::~PyPlugin()
 {
+	Py_CLEAR(m_pyProcess);
+#ifdef _DEBUG
 	cerr << "PyPlugin::PyPlugin:" << m_class 
 	<< " Instance deleted." << endl;
+#endif
 }
 
 
@@ -185,7 +106,7 @@
 
 	char method[]="getIdentifier"; 
 	cerr << "[call] " << method << endl;
-	string rString="VampPy-x";
+	string rString="vampy-x";
 
 	if ( PyObject_HasAttrString(m_pyInstance,method) ) {
 
@@ -203,6 +124,7 @@
 
 		rString=PyString_AsString(pyString);
 		Py_CLEAR(pyString);
+		return rString;
 	}
 	cerr << "Warning: Plugin must return a unique identifier." << endl;
 	return rString;
@@ -336,15 +258,51 @@
 bool
 PyPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
 {
+	
+	//placing Mutex before these calls causes deadlock
+    if (channels < getMinChannelCount() ||
+	channels > getMaxChannelCount()) return false;
+	
+	m_inputDomain = getInputDomain();
+
 	MutexLocker locker(&m_pythonInterpreterMutex);
 
-    if (channels < getMinChannelCount() ||
-	channels > getMaxChannelCount()) return false;
-
-    m_stepSize = std::min(stepSize, blockSize);
+	//useful for debugging Python plugins
 	char method[]="initialise";
 	cerr << "[call] " << method << endl;
 
+	initMaps();
+
+	m_stepSize = stepSize;
+	m_blockSize = blockSize;
+	m_channels = channels;
+
+	//quering process implementation type
+	char legacyMethod[]="process";
+	char numpyMethod[]="processN";
+	m_processType = 0;
+
+	if (PyObject_HasAttrString(m_pyInstance,legacyMethod)) 
+	{ 
+		m_processType = legacyProcess;
+		m_pyProcess = PyString_FromString(legacyMethod);
+	}
+
+	if (PyObject_HasAttrString(m_pyInstance,numpyMethod))
+	{
+		m_processType = numpyProcess;
+		m_pyProcess = PyString_FromString(numpyMethod);
+	}
+	
+	if (!m_processType)
+	{
+		m_processType = not_implemented;
+		m_pyProcess = NULL;		
+		cerr << "Warning: Python plugin [" << m_class << "::" << method 
+		<< "] No process implementation found. Plugin will do nothing." << endl;
+	}
+
+	
 		//Check if the method is implemented in Python else return false
 		if (PyObject_HasAttrString(m_pyInstance,method)) {
    			
@@ -379,17 +337,26 @@
 				Py_CLEAR(pyBool); 
 				return false;}								
 		} 
-    	return true;
+    	return false;
 }
 
 void
 PyPlugin::reset()
 {
-	//!!! implement this!
-    m_previousSample = 0.0f;
+	MutexLocker locker(&m_pythonInterpreterMutex);
+
+	char method[]="reset";
+	cerr << "[call] " << method << endl;
+	
+	if ( PyObject_HasAttrString(m_pyInstance,method) ) {
+
+		PyObject_CallMethod(m_pyInstance, method, NULL);
+		if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }		
+
+	}
 }
 
-PyPlugin::InputDomain PyPlugin::getInputDomain() const 
+PyPlugin::InputDomain PyPlugin::getInputDomain() const  
 { 
 	MutexLocker locker(&m_pythonInterpreterMutex);
 
@@ -416,6 +383,7 @@
     return rValue; 
 }
 
+
 size_t PyPlugin::getPreferredBlockSize() const 
 { 
 	MutexLocker locker(&m_pythonInterpreterMutex);
@@ -517,8 +485,9 @@
 PyPlugin::OutputList
 PyPlugin::getOutputDescriptors() const
 {
+	
 	MutexLocker locker(&m_pythonInterpreterMutex);
-
+	
 	//PyEval_AcquireThread(newThreadState);
 	OutputList list;
 	OutputDescriptor od;
@@ -526,7 +495,7 @@
 	cerr << "[call] " << method << endl;
 
 	//Check if the method is implemented in Python
-	if ( PyObject_HasAttrString(m_pyInstance,method) ) {
+	if ( ! PyObject_HasAttrString(m_pyInstance,method) ) return list;
 			
 		//Call the method: must return list object (new reference)
 		PyObject *pyList = 
@@ -607,13 +576,11 @@
 						break;					
 					default : 	
 						cerr << "Invalid key in VAMP OutputDescriptor: " << PyString_AsString(pyKey) << endl; 
-				} // switch					
-			} // while dict keys
+				} 					
+			} // while dict
 			list.push_back(od);
-		} // for each memeber in outputlist
+		} // for list
 		Py_CLEAR(pyList);
-	} // if method is implemented
-    //PyEval_ReleaseThread(newThreadState);
 	return list;
 }
 
@@ -628,7 +595,7 @@
 	cerr << "[call] " << method << endl;
 
 	//Check if the method is implemented in Python
-	if ( PyObject_HasAttrString(m_pyInstance,method) ) {
+	if ( ! PyObject_HasAttrString(m_pyInstance,method) ) return list;
 			
 		//Call the method: must return list object (new reference)
 		PyObject *pyList = 
@@ -692,12 +659,11 @@
 						break;					
 					default : 	
 						cerr << "Invalid key in VAMP OutputDescriptor: " << PyString_AsString(pyKey) << endl; 
-				} // switch					
-			} // while dict keys
+				} 				
+			} // while dict
 			list.push_back(pd);
-		} // for each memeber in outputlist
+		} // for list
 		Py_CLEAR(pyList);
-	} // if 
 	return list;
 }
 
@@ -779,41 +745,68 @@
 {
 	MutexLocker locker(&m_pythonInterpreterMutex);
 
-    if (m_stepSize == 0) {
+#ifdef _DEBUG	
+	cerr << "[call] process, frame:" << proccounter << endl;
+	proccounter++;
+#endif
+
+    if (m_blockSize == 0) {
 	cerr << "ERROR: PyPlugin::process: "
 	     << "Plugin has not been initialised" << endl;
 	return FeatureSet();
     }
-	static char method[]="process";
 
-#ifdef _DEBUG	
-	cerr << "[call] " << method << " frame:" << proccounter << endl;
-	proccounter++;
-	//cerr << "C: proc..." << proccounter << " " << endl;
-#endif
+	if (m_processType == not_implemented) {
+	cerr << "ERROR: In Python plugin [" << m_class   
+		 << "] No process implementation found. Returning empty feature set." << endl;
+	return FeatureSet();
+	}
 
-	//proces::Check if the method is implemented in Python
-	if ( PyObject_HasAttrString(m_pyInstance,method) )
-	{	
+	string method=PyString_AsString(m_pyProcess);
+
+	
+
+		PyObject *pyOutputList = NULL;
 		
-		//Pack method name into Python Object
-		PyObject *pyMethod = PyString_FromString(method);
+		/*new numPy support*/
+		if (m_processType == numpyProcess) {
+
+		//declare buffer object
+		PyObject *pyBuffer; 
+
+		//Expose memory using the Buffer Interface of C/API		
+		//This will virtually pass a pointer only that can be 
+		//recasted in Python code             
+		pyBuffer = 
+		PyBuffer_FromMemory((void *) (float *) inputBuffers[0], 
+		(Py_ssize_t) sizeof(float) * m_blockSize);
+		
+		//Call python process (returns new reference)
+		pyOutputList = 
+		PyObject_CallMethodObjArgs(m_pyInstance,m_pyProcess,pyBuffer,NULL);
+
+		} 
+		
+		if (m_processType == legacyProcess) { 
 
 		//Declare new list object
 		PyObject *pyFloat, *pyList;
-		pyList = PyList_New((Py_ssize_t) m_stepSize);
+		pyList = PyList_New((Py_ssize_t) m_blockSize);
 
 		//Pack samples into a Python List Object
-		//pyFloat will always be new references, 
+		//pyFloat types will always be new references, 
 		//these will be discarded when the list is deallocated
-		for (size_t i = 0; i < m_stepSize; ++i) {
+		for (size_t i = 0; i < m_blockSize; ++i) {
 		pyFloat=PyFloat_FromDouble((double) inputBuffers[0][i]);
 		PyList_SET_ITEM(pyList, (Py_ssize_t) i, pyFloat);
 		}
-		
+
 		//Call python process (returns new reference)
-		PyObject *pyOutputList = 
-		PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyList,NULL);
+		pyOutputList = 
+		PyObject_CallMethodObjArgs(m_pyInstance,m_pyProcess,pyList,NULL);
+						
+		}
+
 
 		//Check return type
 		if (pyOutputList == NULL || !PyList_Check(pyOutputList) ) {
@@ -825,12 +818,12 @@
 				cerr << "ERROR: In Python plugin [" << m_class << "::" << method 
 				<< "] Expected List return type." << endl;				
 			}
-			Py_CLEAR(pyMethod);
+			//Py_CLEAR(pyMethod);
 			Py_CLEAR(pyOutputList);
 			return FeatureSet();
 		}
 			
-		Py_DECREF(pyMethod);
+		//Py_DECREF(pyMethod);
 		// Py_DECREF(pyList); 
 		// This appears to be tracked by the cyclic garbage collector
 		// hence decrefing produces GC error
@@ -902,9 +895,6 @@
 		}//for i = FeatureSet
 		Py_CLEAR(pyOutputList);
 		return returnFeatures;
-
-	}//if (has_attribute)
-	return FeatureSet(); 
 }
 
 
@@ -994,3 +984,97 @@
 		return returnFeatures;
 }
 
+bool
+PyPlugin::initMaps() const
+{
+
+	if (isMapInitialised) return true;
+
+	outKeys["identifier"] = identifier;
+	outKeys["name"] = name;
+	outKeys["description"] = description;
+	outKeys["unit"] = unit;
+	outKeys["hasFixedBinCount"] = hasFixedBinCount; 
+	outKeys["binCount"] = binCount;
+	outKeys["binNames"] = binNames;
+	outKeys["hasKnownExtents"] = hasKnownExtents;
+	outKeys["minValue"] = minValue;
+	outKeys["maxValue"] = maxValue;
+	outKeys["isQuantized"] = isQuantized;
+	outKeys["quantizeStep"] = quantizeStep;
+	outKeys["sampleType"] = sampleType;
+	outKeys["sampleRate"] = sampleRate;
+
+	sampleKeys["OneSamplePerStep"] = OneSamplePerStep;
+	sampleKeys["FixedSampleRate"] = FixedSampleRate;
+	sampleKeys["VariableSampleRate"] = VariableSampleRate;
+
+	ffKeys["hasTimestamp"] = hasTimestamp;
+	ffKeys["timeStamp"] = timeStamp;
+	ffKeys["values"] = values;
+	ffKeys["label"] = label;
+
+	parmKeys["identifier"] = p::identifier;
+	parmKeys["name"] = p::name;
+	parmKeys["description"] = p::description;
+	parmKeys["unit"] = p::unit;
+	parmKeys["minValue"] = p::minValue;
+	parmKeys["maxValue"] = p::maxValue;
+	parmKeys["defaultValue"] = p::defaultValue;
+	parmKeys["isQuantized"] = p::isQuantized;
+
+	isMapInitialised = true;
+	return true;
+}
+
+
+//missing API helper: convert Python list to C++ vector of strings
+//TODO: these could be templates if we need more of this kind
+std::vector<std::string> 
+PyPlugin::PyList_To_StringVector (PyObject *inputList) const {
+	
+	std::vector<std::string> Output;
+	std::string ListElement;
+	PyObject *pyString = NULL;
+	
+	if (!PyList_Check(inputList)) return Output;
+
+	for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
+		//Get next list item (Borrowed Reference)
+		pyString = PyList_GET_ITEM(inputList,i);
+		ListElement = (string) PyString_AsString(PyObject_Str(pyString));
+		Output.push_back(ListElement);
+	}
+	return Output;
+}
+
+//missing API helper: convert Python list to C++ vector of floats
+std::vector<float> 
+PyPlugin::PyList_As_FloatVector (PyObject *inputList) const {
+	
+	std::vector<float> Output;
+	float ListElement;
+	PyObject *pyFloat = NULL;
+	
+	if (!PyList_Check(inputList)) return Output; 
+
+	for (Py_ssize_t k = 0; k < PyList_GET_SIZE(inputList); ++k) {
+		//Get next list item (Borrowed Reference)
+		pyFloat =  PyList_GET_ITEM(inputList,k);
+		ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
+		Output.push_back(ListElement);
+	}
+
+	return Output;
+}
+
+/* TODO: find out why this produces error, also 
+		do sg more clever about handling RealTime
+Vamp::RealTime 
+PyFrame_As_RealTime (PyObject *frameNo,size_t inputSampleRate) {
+Vamp::RealTime result =  
+Vamp::RealTime::frame2RealTime((size_t)PyInt_AS_LONG(frameNo), inputSampleRate);
+return result;
+}
+*/
+
--- a/PyPlugin.h	Fri Mar 14 12:09:34 2008 +0000
+++ b/PyPlugin.h	Wed Mar 19 16:02:29 2008 +0000
@@ -92,6 +92,11 @@
 	label
 	};
 
+enum eProcessType {
+	not_implemented,
+	legacyProcess,
+	numpyProcess
+	};
 
 class PyPlugin : public Vamp::Plugin
 {
@@ -101,7 +106,7 @@
 
     bool initialise(size_t channels, size_t stepSize, size_t blockSize);
     void reset();
-	//virtuals:
+
 	InputDomain getInputDomain() const;
 	size_t getPreferredBlockSize() const;
 	size_t getPreferredStepSize() const; 
@@ -128,10 +133,18 @@
 protected:
 	PyObject *m_pyInstance;
     size_t m_stepSize;
-    float m_previousSample;
+    size_t m_blockSize;
+    size_t m_channels;
 	std::string m_plugin;
 	std::string m_class;
 	std::string m_path;
+	int m_processType;
+	PyObject *m_pyProcess;
+	InputDomain m_inputDomain;
+	
+	bool initMaps() const;
+	std::vector<std::string> PyList_To_StringVector (PyObject *inputList) const;
+	std::vector<float> PyList_As_FloatVector (PyObject *inputList) const;
 
 	static Mutex m_pythonInterpreterMutex;
 };
--- a/pyvamp-main.cpp	Fri Mar 14 12:09:34 2008 +0000
+++ b/pyvamp-main.cpp	Wed Mar 19 16:02:29 2008 +0000
@@ -61,7 +61,7 @@
 using std::string;
 using std::vector;
 
-volatile bool mutex = false;
+//volatile bool mutex = false;
 static int adinstcount;
 
 class PyPluginAdapter : public Vamp::PluginAdapterBase
@@ -149,7 +149,7 @@
 		scanner = PyPlugScanner::getInstance();
 		pyPath=scanner->getAllValidPath();
 		//add this as extra path for development
-		pyPath.push_back("/Users/Shared/Development/vamp-experiments");
+		//pyPath.push_back("/Users/Shared/Development/vamp-experiments");
 		scanner->setPath(pyPath);
 		pyPlugs = scanner->getPyPlugs();
 		cerr << "Found " << pyPlugs.size() << " Scripts ...OK" << endl;
@@ -161,6 +161,7 @@
 			adapters.push_back( new PyPluginAdapter(pyPlugs[i],pyInstances[i]));
 		} 
 		haveScannedPlugins=true;		
+		
 	}
 
 	cerr << "Accessing adapter index: " << index << " (adapters: " << adapters.size() << ")" << endl;