From ec67ac9af1c9a02130347c4ed6f32fa03f55eba2 Mon Sep 17 00:00:00 2001
From: Thomas Grill <xovo@users.sourceforge.net>
Date: Thu, 10 Mar 2005 04:59:00 +0000
Subject: more buffer functionality (support sequence and number protocols)
 more examples preset sys.argv for module loading support for buffer objects
 (preliminary)

svn path=/trunk/; revision=2615
---
 externals/grill/py/pd/buffer-1.pd      |  63 +++--
 externals/grill/py/readme.txt          |   5 +-
 externals/grill/py/scripts/buffer.py   |  50 ++--
 externals/grill/py/source/main.cpp     |  32 ++-
 externals/grill/py/source/pybuffer.cpp | 496 ++++++++++++++++++++++++++++++---
 5 files changed, 552 insertions(+), 94 deletions(-)

(limited to 'externals')

diff --git a/externals/grill/py/pd/buffer-1.pd b/externals/grill/py/pd/buffer-1.pd
index 2309ca30..ca799385 100644
--- a/externals/grill/py/pd/buffer-1.pd
+++ b/externals/grill/py/pd/buffer-1.pd
@@ -1,39 +1,40 @@
-#N canvas 123 58 692 472 12;
+#N canvas 123 58 712 492 12;
 #X obj 37 240 print;
 #X obj 107 241 print A;
 #X msg 30 139 reload;
 #N canvas 0 0 450 300 graph1 0;
 #X array array1 100 float 3;
-#A 0 0 0 0 0 0 0 0 0 0 0 0.0285713 0.042857 0.042857 0.042857 0.042857
-0.042857 0.0142857 0.0142857 0.0142857 -0.0285713 -0.0571427 -0.0999997
--0.171428 -0.185714 -0.199999 -0.271428 -0.342856 -0.385713 -0.385713
--0.385713 -0.385713 -0.385713 -0.385713 -0.385713 -0.385713 -0.357142
--0.357142 -0.357142 -0.335713 -0.314285 -0.299999 -0.285713 -0.271428
--0.257142 -0.242856 -0.228571 -0.214285 -0.185714 -0.157142 -0.128571
--0.0999997 -0.085714 -0.0714283 -0.042857 -0.0142857 0.0142857 0.042857
-0.0523808 0.0619046 0.0714283 0.114285 0.15 0.214285 0.257142 0.228571
-0.207142 0.185714 0.157142 0.085714 0.0142857 0.0142857 0.0142857 -0.0571427
--0.0571427 -0.0999997 -0.0999997 -0.0999997 -0.171428 -0.171428 -0.158646
--0.142105 -0.125564 -0.109022 -0.092481 -0.0759397 -0.0593984 -0.042857
--0.0175824 0.00769227 0.0329669 0.0582416 0.0835162 0.108791 0.134065
-0.15934 0.184615 0.209889 0.235164 0.260439 0.32857;
+#A 0 0 0 0 0 0 0 0 0 0 0 0.00285713 0.00471427 0.00514284 0.00557141
+0.00599998 0.00642855 0.00228571 0.00242857 0.00257143 -0.00542855
+-0.0114285 -0.0209999 -0.0377142 -0.0427142 -0.0479998 -0.067857 -0.0891426
+-0.104143 -0.108 -0.111857 -0.115714 -0.119571 -0.123428 -0.127285
+-0.131142 -0.125 -0.128571 -0.132143 -0.127571 -0.122571 -0.12 -0.117142
+-0.114 -0.110571 -0.106857 -0.102857 -0.0985711 -0.0872856 -0.0754282
+-0.0629998 -0.0499999 -0.0437141 -0.0371427 -0.0227142 -0.00771428
+0.00785714 0.0239999 0.0298571 0.0359047 0.0421427 0.068571 0.0915
+0.132857 0.161999 0.146285 0.134642 0.122571 0.105285 0.0582855 0.00985713
+0.00999999 0.0101428 -0.0411427 -0.0417142 -0.0739998 -0.0749998 -0.0759998
+-0.132 -0.133714 -0.12533 -0.113684 -0.101707 -0.089398 -0.0767592
+-0.0637893 -0.0504886 -0.036857 -0.0152967 0.0067692 0.0293405 0.0524174
+0.0759997 0.100088 0.12468 0.14978 0.175384 0.201493 0.228109 0.25523
+0.325284;
 #X coords 0 1 99 -1 200 140 1;
 #X restore 421 156 graph;
 #N canvas 0 0 450 300 graph2 0;
 #X array array2 100 float 3;
-#A 0 0 0 0 0 0 0 0.0285712 0.0428568 0.0571424 0.0999993 0.114285 0.128571
-0.142856 0.157142 0.171427 0.185713 0.199999 0.242855 0.257141 0.271426
-0.314283 0.342854 0.385711 0.421425 0.485711 0.557139 0.599995 0.671424
-0.680947 0.690471 0.699995 0.742852 0.752375 0.761899 0.771423 0.771423
-0.771423 0.81428 0.81428 0.81428 0.81428 0.828565 0.842851 0.842851
-0.842851 0.842851 0.842851 0.842851 0.864279 0.885708 0.885708 0.885708
-0.885708 0.876184 0.86666 0.857136 0.857136 0.857137 0.842851 0.828565
-0.81428 0.799994 0.785708 0.76428 0.742852 0.728566 0.71428 0.671424
-0.599995 0.428568 0.40714 -0.328569 -0.428569 -0.428569 -0.471425 -0.471425
--0.471425 -0.442854 -0.442854 -0.399997 -0.385712 -0.371426 -0.335712
--0.299998 -0.257141 -0.242856 -0.22857 -0.157142 -0.114285 -0.0857139
--0.0857139 -0.042857 -0.042857 0.028571 0.0571425 0.0571425 0.0999993
-0.128571 0.128571 0.128571;
+#A 0 0 0 0 0 0 0 0.0285712 0.0428568 0.0571424 0.12857 0.171427 0.185712
+0.199998 0.242854 0.342853 0.342853 0.364281 0.41428 0.41428 0.357138
+0.314282 0.278568 0.314282 0.328567 0.342853 0.378567 0.41428 0.457137
+0.49285 0.528564 0.54285 0.557135 0.599992 0.614277 0.671419 0.671419
+0.599992 0.614276 0.59999 0.585705 0.571419 0.499991 0.482135 0.464278
+0.446421 0.428564 0.408564 0.388565 0.368565 0.348565 0.328566 0.305709
+0.282852 0.259995 0.237138 0.214282 0.194282 0.174282 0.154282 0.134283
+0.114283 0.0914263 0.0685695 0.0457127 0.0228559 8.84384e-007 0.0142864
+0.0285719 0.0428574 0.0571429 0.0714284 0.096428 0.121428 0.146427
+0.171427 0.181631 0.191835 0.202039 0.212243 0.222446 0.23265 0.242854
+0.25714 0.271425 0.285711 0.299996 0.314282 0.33571 0.357138 0.385709
+0.407138 0.428566 0.457137 0.457137 0.12857 0.514279 0.557135 0.604754
+0.652372 0.814274;
 #X coords 0 1 99 -1 200 140 1;
 #X restore 421 305 graph;
 #N canvas 0 0 450 300 graph3 0;
@@ -41,16 +42,20 @@
 #X coords 0 1 99 -1 200 140 1;
 #X restore 65 301 graph;
 #X obj 36 199 py buffer @detach 1;
-#X msg 123 127 mul array3 array1 array2;
-#X msg 123 149 add array3 array1 array2;
+#X msg 192 127 mul array3 array1 array2;
+#X msg 192 149 add array3 array1 array2;
 #X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818
 -1 0;
 #X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill;
 #X text 235 32 http://grrrr.org/ext;
 #X text 17 67 This demonstrates the usage of buffers. See the buffer.py
 script.;
+#X msg 193 176 fadein array1;
+#X msg 191 200 neg array2;
 #X connect 2 0 6 0;
 #X connect 6 0 0 0;
 #X connect 6 1 1 0;
 #X connect 7 0 6 1;
 #X connect 8 0 6 1;
+#X connect 13 0 6 1;
+#X connect 14 0 6 1;
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt
index ff2266dd..60260706 100644
--- a/externals/grill/py/readme.txt
+++ b/externals/grill/py/readme.txt
@@ -83,7 +83,7 @@ Version history:
 - ADD: Python symbol type
 - ADD: _del method in pyext-derived class can be used to clean up things on exit
 - FIX: solved py->py messaging problem with lock count instead of message queuing
-- ADD: numarray support for buffer handling
+- ADD: buffer handling with optional numarray support (if present)
 
 0.1.4:
 - ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__)
@@ -146,6 +146,9 @@ Version history:
 
 TODO list:
 
+bugs:
+- crashes with long Python printouts
+
 general:
 - Documentation and better example patches
 - better error reporting for runtime errors
diff --git a/externals/grill/py/scripts/buffer.py b/externals/grill/py/scripts/buffer.py
index 4c81caab..19b6f5d3 100644
--- a/externals/grill/py/scripts/buffer.py
+++ b/externals/grill/py/scripts/buffer.py
@@ -7,12 +7,9 @@
 
 """This is an example script for the py/pyext object's buffer support.
 
-PD/Max buffers can be imported to and exported from numarray arrays.
+PD/Max buffers can be mapped to numarray arrays.
 For numarray see http://numeric.scipy.org
-It will probably once be replaced by Numeric
-
-- _import(buffer): copy contents from the buffer to a new numarray object
-- _export(buffer,numarray): export contents of numarray object to the buffer
+It will probably once be replaced by Numeric(3)
 """
 
 import sys
@@ -20,7 +17,7 @@ import sys
 try:
     import pyext
 except:
-    print "ERROR: This script must be loaded by the PD/Max pyext external"
+    print "ERROR: This script must be loaded by the PD/Max py/pyext external"
 
 try:    
     from numarray import *
@@ -28,19 +25,36 @@ except:
     print "Failed importing numarray module:",sys.exc_value
 
 def mul(*args):
+    # create buffer objects
+    # as long as these variables live the underlying buffers are locked
     c = pyext.Buffer(args[0])
-    dst = c.array()
-    dst[:] = 0
-    a = pyext.Buffer(args[1]).array()
-    b = pyext.Buffer(args[2]).array()
-    dst += a*b
-    c.dirty()   
+    a = pyext.Buffer(args[1])
+    b = pyext.Buffer(args[2])
+
+    # slicing causes numarrays (mapped to buffers) to be created
+    # note the c[:] - to assign contents you must assign to a slice of the buffer
+    c[:] = a[:]*b[:]  
 
 def add(*args):
     c = pyext.Buffer(args[0])
-    dst = c.array()
-    dst[:] = 0
-    a = pyext.Buffer(args[1]).array()
-    b = pyext.Buffer(args[2]).array()
-    dst += a+b
-    c.dirty()   
+    a = pyext.Buffer(args[1])
+    b = pyext.Buffer(args[2])
+
+    # this is also possible, but is probably slower
+    # the + converts a into a numarray, the argument b is taken as a sequence
+    # depending on the implementation in numarray this may be as fast
+    # as above or not
+    c[:] = a+b  
+
+def fadein(target):
+    a = pyext.Buffer(target)
+    # in place operations are ok
+    a *= arange(len(a),type=Float32)/len(a)
+
+def neg(target):
+    a = pyext.Buffer(target)
+    # in place transformation (see numarray ufuncs)
+    negative(a[:],a[:])
+    # must mark buffer content as dirty to update graph
+    # (no explicit assignment occurred)
+    a.dirty() 
diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp
index c24f998c..e32b9ba8 100644
--- a/externals/grill/py/source/main.cpp
+++ b/externals/grill/py/source/main.cpp
@@ -97,12 +97,30 @@ void py::lib_setup()
     pythrmap[GetThreadId()] = pythrmain;
 #endif
 
+    // sys.argv must be set to empty tuple
+    char *nothing = "";
+	PySys_SetArgv(0,&nothing);
+
     // register/initialize pyext module only once!
 	module_obj = Py_InitModule(PYEXT_MODULE, func_tbl);
 	module_dict = PyModule_GetDict(module_obj); // borrowed reference
 
 	PyModule_AddStringConstant(module_obj,"__doc__",(char *)py_doc);
 
+	// redirect stdout
+	PyObject* py_out;
+    py_out = Py_InitModule("stdout", StdOut_Methods);
+	PySys_SetObject("stdout", py_out);
+    py_out = Py_InitModule("stderr", StdOut_Methods);
+	PySys_SetObject("stderr", py_out);
+
+    // get garbage collector function
+    PyObject *gcobj = PyImport_ImportModule("gc");
+    if(gcobj) {
+        gcollect = PyObject_GetAttrString(gcobj,"collect");
+        Py_DECREF(gcobj);
+    }
+
     // add symbol type
     initsymbol();
     PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type);
@@ -119,20 +137,6 @@ void py::lib_setup()
     initsamplebuffer();
     PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type);
 
-	// redirect stdout
-	PyObject* py_out;
-    py_out = Py_InitModule("stdout", StdOut_Methods);
-	PySys_SetObject("stdout", py_out);
-    py_out = Py_InitModule("stderr", StdOut_Methods);
-	PySys_SetObject("stderr", py_out);
-
-    // get garbage collector function
-    PyObject *gcobj = PyImport_ImportModule("gc");
-    if(gcobj) {
-        gcollect = PyObject_GetAttrString(gcobj,"collect");
-        Py_DECREF(gcobj);
-    }
-
 	// -------------------------------------------------------------
 
 	FLEXT_SETUP(pyobj);
diff --git a/externals/grill/py/source/pybuffer.cpp b/externals/grill/py/source/pybuffer.cpp
index ed1b2749..96f2efae 100644
--- a/externals/grill/py/source/pybuffer.cpp
+++ b/externals/grill/py/source/pybuffer.cpp
@@ -101,31 +101,6 @@ static PyGetSetDef buffer_getseters[] = {
     {NULL}  /* Sentinel */
 };
 
-static PyObject *buffer_array(PyObject *obj)
-{
-    PyObject *ret;
-#ifdef PY_NUMARRAY
-    if(nasupport) {
-        pySamplebuffer *self = (pySamplebuffer *)obj;
-        if(self->buf) {
-            maybelong shape[2];
-            shape[0] = self->buf->Frames();
-            shape[1] = self->buf->Channels();
-            ret = (PyObject *)NA_NewAllFromBuffer(2,shape,numtype,(PyObject *)self,0,sizeof(t_sample *),NA_ByteOrder(),1,1);
-        }
-        else
-            Py_INCREF(ret = Py_None);
-    }
-    else {
-        PyErr_Format(PyExc_RuntimeError,"No numarray support");
-        ret = NULL;
-    }
-#else
-    Py_INCREF(ret = Py_None);
-#endif
-    return ret;
-}
-
 static PyObject *buffer_dirty(PyObject *obj)
 {
     ((pySamplebuffer *)obj)->dirty = true;
@@ -134,7 +109,6 @@ static PyObject *buffer_dirty(PyObject *obj)
 }
 
 static PyMethodDef buffer_methods[] = {
-    {"array", (PyCFunction)buffer_array,METH_NOARGS,"Return a numarray object"},
     {"dirty", (PyCFunction)buffer_dirty,METH_NOARGS,"Mark buffer as dirty"},
     {NULL}  /* Sentinel */
 };
@@ -170,13 +144,470 @@ static int buffer_charbuffer(PyObject *obj, int segment, const char **ptrptr)
     return b->Channels()*b->Frames()*sizeof(t_sample);
 }
 
-static PyBufferProcs bufferprocs = {
+static PyBufferProcs buffer_as_buffer = {
     buffer_readbuffer,
     buffer_writebuffer,
     buffer_segcount,
     buffer_charbuffer
 };
 
+static int buffer_length(pySamplebuffer *self)
+{
+    return self->buf?self->buf->Frames():0;
+}
+
+static PyObject *buffer_item(pySamplebuffer *self, int i)
+{
+    PyObject *ret;
+    if(self->buf) {
+	    if (i < 0 || i >= self->buf->Frames()) {
+		    PyErr_SetString(PyExc_IndexError,"Index out of range");
+		    ret = NULL;
+	    }
+        else {
+            if(self->buf->Channels() == 1)
+                ret = PyFloat_FromDouble(self->buf->Data()[i]);
+            else {
+		        PyErr_SetString(PyExc_NotImplementedError,"Multiple channels not implemented yet");
+		        ret = NULL;
+            }
+        }
+    }
+    else
+        Py_INCREF(ret = Py_None);
+	return ret;
+}
+
+static PyObject *buffer_slice(pySamplebuffer *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2))
+{
+    PyObject *ret;
+#ifdef PY_NUMARRAY
+    if(nasupport) {
+        if(self->buf) {
+            const int n = self->buf->Frames();
+            const int c = self->buf->Channels();
+            if(ilow < 0) ilow += n;
+            if(ilow >= n) ilow = n-1;
+            if(ihigh < 0) ihigh += n;
+            if(ihigh > n) ihigh = n;
+
+            maybelong shape[2];
+            shape[0] = n;
+            shape[1] = c;
+            PyObject *nobj = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,(PyObject *)self,0,0,NA_ByteOrder(),1,1);
+            if(ilow != 0 || ihigh != n) {
+                ret = PySequence_GetSlice(nobj,ilow,ihigh);
+                Py_DECREF(nobj);
+            }
+            else
+                ret = nobj;
+        }
+        else
+            Py_INCREF(ret = Py_None);
+    }
+    else 
+#endif
+    {
+        PyErr_SetString(PyExc_RuntimeError,"No numarray support");
+        ret = NULL;
+    }
+    return ret;
+}
+
+static int buffer_ass_item(pySamplebuffer *self,int i,PyObject *v)
+{
+    int ret;
+    if(self->buf) {
+	    if (i < 0 || i >= self->buf->Frames()) {
+		    PyErr_Format(PyExc_IndexError,"Index out of range");
+		    ret = -1;
+	    }
+        else {
+            if(self->buf->Channels() == 1) {
+                self->buf->Data()[i] = (t_sample)PyFloat_AsDouble(v);
+                if(PyErr_Occurred()) {
+                    // cast to double failed
+    		        PyErr_SetString(PyExc_TypeError,"Value must be a numarray");
+                    ret = -1;
+                }
+                else {
+                    self->dirty = true;
+                    ret = 0;
+                }
+            }
+            else {
+		        PyErr_SetString(PyExc_NotImplementedError,"Multiple channels not implemented yet");
+		        ret = -1;
+            }
+        }
+    }
+    else
+        ret = -1;
+	return ret;
+}
+
+static int buffer_ass_slice(pySamplebuffer *self,int ilow,int ihigh,PyObject *value)
+{
+    int ret;
+#ifdef PY_NUMARRAY
+    if(nasupport) {
+        if(!value) {
+            PyErr_SetString(PyExc_TypeError,"Object doesn't support item deletion");
+            ret = -1;
+        }
+        else if(self->buf) {
+            const int n = self->buf->Frames();
+            const int c = self->buf->Channels();
+            if(ilow < 0) ilow += n;
+            if(ilow >= n) ilow = n-1;
+            if(ihigh < 0) ihigh += n;
+            if(ihigh > n) ihigh = n;
+
+            PyArrayObject *out = NA_InputArray(value,numtype,NUM_C_ARRAY);
+            if(!out) {
+                PyErr_SetString(PyExc_TypeError,"Assigned object must be a numarray");
+                ret = -1;
+            }
+            else if(out->nd != 1) {
+                PyErr_SetString(PyExc_NotImplementedError,"Multiple dimensions not supported yet");
+                ret = -1;
+            }
+            else {
+                int dlen = ihigh-ilow;
+                int slen = out->dimensions[0];
+                flext::CopySamples(self->buf->Data()+ilow,(t_sample *)NA_OFFSETDATA(out),slen < dlen?slen:dlen);
+                self->dirty = true;
+                ret = 0;
+            }
+
+            Py_XDECREF(out);
+        }
+        else {
+            PyErr_SetString(PyExc_ValueError,"Buffer is not assigned");
+            ret = -1;
+        }
+    }
+    else 
+#endif
+    {
+        PyErr_SetString(PyExc_RuntimeError,"No numarray support");
+        ret = -1;
+    }
+    return ret;
+}
+
+static PyObject *buffer_concat(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PySequence_Concat(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_repeat(pySamplebuffer *self,int rep)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PySequence_Repeat(nobj,rep);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+
+static PySequenceMethods buffer_as_seq = {
+	(inquiry)buffer_length,			/* inquiry sq_length;             /* __len__ */
+	(binaryfunc)buffer_concat,          /* __add__ */
+	(intargfunc)buffer_repeat,          /* __mul__ */
+	(intargfunc)buffer_item,			/* intargfunc sq_item;            /* __getitem__ */
+	(intintargfunc)buffer_slice,		 /* intintargfunc sq_slice;        /* __getslice__ */
+	(intobjargproc)buffer_ass_item,		/* intobjargproc sq_ass_item;     /* __setitem__ */
+	(intintobjargproc)buffer_ass_slice,	/* intintobjargproc sq_ass_slice; /* __setslice__ */
+};
+
+static PyObject *buffer_iter(PyObject *obj)
+{
+    pySamplebuffer *self = (pySamplebuffer *)obj;
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *it = PyObject_GetIter(nobj);
+        Py_DECREF(nobj);
+        return it;
+    }
+    else
+        return NULL;
+}
+
+
+static PyObject *buffer_add(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Add(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_subtract(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Subtract(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_multiply(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Multiply(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_divide(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Divide(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_remainder(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Remainder(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_divmod(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Divmod(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_power(pySamplebuffer *self,PyObject *op1,PyObject *op2)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Power(nobj,op1,op2);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_negative(pySamplebuffer *self)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Negative(nobj);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_pos(pySamplebuffer *self)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Positive(nobj);
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_absolute(pySamplebuffer *self)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_Absolute(nobj);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static int buffer_coerce(pySamplebuffer **pm, PyObject **pw) 
+{
+    if(pySamplebuffer_Check(*pw)) {
+        Py_INCREF(*pm);
+        Py_INCREF(*pw);
+    	return 0;
+    }
+    else
+        return 1;
+}
+	
+static PyObject *buffer_inplace_add(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlaceAdd(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_inplace_subtract(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlaceSubtract(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_inplace_multiply(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlaceMultiply(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_inplace_divide(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlaceDivide(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_inplace_remainder(pySamplebuffer *self,PyObject *op)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlaceRemainder(nobj,op);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+static PyObject *buffer_inplace_power(pySamplebuffer *self,PyObject *op1,PyObject *op2)
+{
+    PyObject *nobj = buffer_slice(self);
+    if(nobj) {
+        PyObject *ret = PyNumber_InPlacePower(nobj,op1,op2);
+        if(ret == nobj) self->dirty = true;
+        Py_DECREF(nobj);
+        return ret;
+    }
+    else
+        return NULL;
+}
+
+
+
+static PyNumberMethods buffer_as_number = {
+	(binaryfunc)buffer_add, /*nb_add*/
+	(binaryfunc)buffer_subtract, /*nb_subtract*/
+	(binaryfunc)buffer_multiply, /*nb_multiply*/
+	(binaryfunc)buffer_divide, /*nb_divide*/
+	(binaryfunc)buffer_remainder, /*nb_remainder*/
+	(binaryfunc)buffer_divmod, /*nb_divmod*/
+	(ternaryfunc)buffer_power, /*nb_power*/
+	(unaryfunc)buffer_negative, 
+	(unaryfunc)buffer_pos, /*nb_pos*/ 
+	(unaryfunc)buffer_absolute, /* (unaryfunc)buffer_abs,  */
+	0, //(inquiry)buffer_nonzero, /*nb_nonzero*/
+	0,		/*nb_invert*/
+	0,		/*nb_lshift*/
+	0,		/*nb_rshift*/
+	0,		/*nb_and*/
+	0,		/*nb_xor*/
+	0,		/*nb_or*/
+	(coercion)buffer_coerce, /*nb_coerce*/
+	0, /*nb_int*/
+	0, /*nb_long*/
+	0, /*nb_float*/
+	0,		/*nb_oct*/
+	0,		/*nb_hex*/
+	(binaryfunc)buffer_inplace_add,		/* nb_inplace_add */
+	(binaryfunc)buffer_inplace_subtract,		/* nb_inplace_subtract */
+	(binaryfunc)buffer_inplace_multiply,		/* nb_inplace_multiply */
+	(binaryfunc)buffer_inplace_divide,		/* nb_inplace_divide */
+	(binaryfunc)buffer_inplace_remainder,		/* nb_inplace_remainder */
+	(ternaryfunc)buffer_inplace_power, 		/* nb_inplace_power */
+	0,		/* nb_inplace_lshift */
+	0,		/* nb_inplace_rshift */
+	0,		/* nb_inplace_and */
+	0,		/* nb_inplace_xor */
+	0,		/* nb_inplace_or */
+//	buffer_floor_div, /* nb_floor_divide */
+//	buffer_div,	/* nb_true_divide */
+//	buffer_inplace_floor_div,		/* nb_inplace_floor_divide */
+//	buffer_inplace_div,		/* nb_inplace_true_divide */
+};
+
 PyTypeObject pySamplebuffer_Type = {
     PyObject_HEAD_INIT(NULL)
     0,                         /*ob_size*/
@@ -189,22 +620,22 @@ PyTypeObject pySamplebuffer_Type = {
     0,                         /*tp_setattr*/
     0,            /*tp_compare*/
     buffer_repr,               /*tp_repr*/
-    0,                         /*tp_as_number*/
-    0,                         /*tp_as_sequence*/
+    &buffer_as_number,                         /*tp_as_number*/
+    &buffer_as_seq,                 /*tp_as_sequence*/
     0,                         /*tp_as_mapping*/
     buffer_hash,               /*tp_hash */
     0,                         /*tp_call*/
     0,                         /*tp_str*/
     0,                         /*tp_getattro*/
     0,                         /*tp_setattro*/
-    &bufferprocs,             /*tp_as_buffer*/
+    &buffer_as_buffer,             /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/,   /*tp_flags*/
     "Samplebuffer objects",           /* tp_doc */
     0,		               /* tp_traverse */
     0,		               /* tp_clear */
     0 /*buffer_richcompare*/,	       /* tp_richcompare */
     0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
+    buffer_iter,		               /* tp_iter */
     0,		               /* tp_iternext */
     buffer_methods,                          /* tp_methods */
     0,            /* tp_members */
@@ -222,10 +653,11 @@ PyTypeObject pySamplebuffer_Type = {
 void initsamplebuffer()
 {
 #ifdef PY_NUMARRAY
+    PyErr_Clear();
     import_libnumarray();
     if(PyErr_Occurred())
         // catch import error
-        PyErr_Clear();
+        PyErr_Print();
     else {
         // numarray support ok
         nasupport = true;
-- 
cgit v1.2.1