Mercurial > hg > vampy-host
changeset 124:bea7cf4126b5
Add RealTime tests, simplify allocations & a couple of fixes
author | Chris Cannam |
---|---|
date | Wed, 24 Jun 2015 14:11:19 +0100 |
parents | 89cc3595c404 |
children | ece31f26017e |
files | native/PyPluginObject.cpp native/PyRealTime.cpp test/test_realtime.py vamp/__init__.py |
diffstat | 4 files changed, 193 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/native/PyPluginObject.cpp Wed Jun 24 10:50:13 2015 +0100 +++ b/native/PyPluginObject.cpp Wed Jun 24 14:11:19 2015 +0100 @@ -82,8 +82,9 @@ PyObject * PyPluginObject_From_Plugin(Plugin *plugin) { - PyPluginObject *pd = - (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0); + PyPluginObject *pd = PyObject_New(PyPluginObject, &Plugin_Type); + if (!pd) return 0; + pd->plugin = plugin; pd->isInitialised = false; pd->channels = 0; @@ -821,9 +822,9 @@ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ + 0, /*tp_alloc*/ 0, /*tp_new*/ - PyObject_Del, /*tp_free*/ + 0, /*tp_free*/ 0, /*tp_is_gc*/ };
--- a/native/PyRealTime.cpp Wed Jun 24 10:50:13 2015 +0100 +++ b/native/PyRealTime.cpp Wed Jun 24 14:11:19 2015 +0100 @@ -42,36 +42,58 @@ using namespace std; using namespace Vamp; +#if (PY_MAJOR_VERSION >= 3) +#define PyInt_AS_LONG PyLong_AS_LONG +#define PyInt_FromSsize_t PyLong_FromSsize_t +#endif + /* CONSTRUCTOR: New RealTime object from sec and nsec */ static PyObject* RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - unsigned int sec = 0; - unsigned int nsec = 0; + int sec = 0; + int nsec = 0; + int unaryInt = 0; double unary = 0; const char *fmt = NULL; - if ( - /// new RealTime from ('format',float) e.g. ('seconds',2.34123) - !PyArg_ParseTuple(args, "|sd:RealTime.new ", - (const char *) &fmt, - (double *) &unary) && + if (!PyArg_ParseTuple(args, ":RealTime.new ")) { // zero time - /// new RealTime from (sec{int},nsec{int}) e.g. (2,34) - !PyArg_ParseTuple(args, "|II:RealTime.new ", - (unsigned int*) &sec, - (unsigned int*) &nsec) - - ) { - PyErr_SetString(PyExc_TypeError, - "RealTime constructor requires either (sec,nsec) integer tuple, or ('format',float) where 'format' is 'seconds' or 'milliseconds'"); - return NULL; + PyErr_Clear(); + + /// new RealTime from exact ('format',int) e.g. ('milliseconds',200) + if (!PyArg_ParseTuple(args, "si:RealTime.new ", + (const char *) &fmt, + (int *) &unaryInt)) { + + PyErr_Clear(); + + /// new RealTime from ('format',float) e.g. ('seconds',2.34123) + if (!PyArg_ParseTuple(args, "sd:RealTime.new ", + (const char *) &fmt, + (double *) &unary)) { + + PyErr_Clear(); + + /// new RealTime from (sec{int},nsec{int}) e.g. (2,34) + if (!PyArg_ParseTuple(args, "ii:RealTime.new ", + (int*) &sec, + (int*) &nsec)) { + + PyErr_SetString(PyExc_TypeError, + "RealTime constructor requires either (sec,nsec) integer tuple, or ('format',float) where 'format' is 'seconds' or 'milliseconds'"); + return NULL; + } + } + } } PyErr_Clear(); - // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); - RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0); + // Using PyObject_New because we use PyObject_Del to delete in the + // destructor + RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); + PyObject_Init((PyObject *)self, &RealTime_Type); if (self == NULL) return NULL; @@ -84,13 +106,22 @@ else { /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3) if (!string(fmt).compare("float") || - !string(fmt).compare("seconds")) - self->rt = new RealTime( - RealTime::fromSeconds((double) unary)); + !string(fmt).compare("seconds")) { - if (!string(fmt).compare("milliseconds")) { - self->rt = new RealTime( - RealTime::fromSeconds((double) unary / 1000.0)); } + if (unaryInt != 0) { + self->rt = new RealTime(RealTime::fromMilliseconds(unaryInt * 1000)); + } else { + self->rt = new RealTime(RealTime::fromSeconds(unary)); + } + + } else if (!string(fmt).compare("milliseconds")) { + + if (unaryInt != 0) { + self->rt = new RealTime(RealTime::fromMilliseconds(unaryInt)); + } else { + self->rt = new RealTime(RealTime::fromSeconds(unary / 1000.0)); + } + } } if (!self->rt) { @@ -106,10 +137,12 @@ static void RealTimeObject_dealloc(RealTimeObject *self) { - if (self->rt) delete self->rt; //delete the C object - PyObject_Del(self); //delete the Python object (original) - /// this requires PyType_Ready() which fills ob_type - // self->ob_type->tp_free((PyObject*)self); + delete self->rt; // delete the C object + + // "If the type is not subtypable (doesn’t have the + // Py_TPFLAGS_BASETYPE flag bit set), it is permissible to call + // the object deallocator directly instead of via tp_free" + PyObject_Del(self); // delete the Python object (original) } /* RealTime Object's Methods */ @@ -161,10 +194,10 @@ /* Type object's (RealTime) methods table */ static PyMethodDef RealTime_methods[] = { - {"values", (PyCFunction)RealTime_values, METH_NOARGS, + {"values", (PyCFunction)RealTime_values, METH_NOARGS, PyDoc_STR("values() -> Tuple of sec,nsec representation.")}, - {"to_string", (PyCFunction)RealTime_toString, METH_NOARGS, + {"to_string", (PyCFunction)RealTime_toString, METH_NOARGS, PyDoc_STR("to_string() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")}, {"to_frame", (PyCFunction)RealTime_toFrame, METH_VARARGS, @@ -182,21 +215,16 @@ /* Object Protocol */ -#if (PY_MAJOR_VERSION >= 3) -#define PyInt_AS_LONG PyLong_AS_LONG -#define PyInt_FromSsize_t PyLong_FromSsize_t -#endif - static int RealTime_setattr(RealTimeObject *self, char *name, PyObject *value) { - if ( !string(name).compare("sec")) { - self->rt->sec= (int) PyInt_AS_LONG(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); + if (!string(name).compare("nsec")) { + self->rt->nsec = (int) PyInt_AS_LONG(value); return 0; } @@ -279,9 +307,9 @@ static PyObject * RealTime_add(PyObject *s, PyObject *w) { - RealTimeObject *result = - PyObject_New(RealTimeObject, &RealTime_Type); + RealTimeObject *result = PyObject_New(RealTimeObject, &RealTime_Type); if (result == NULL) return NULL; + PyObject_Init((PyObject *)result, &RealTime_Type); result->rt = new RealTime( *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt); @@ -291,9 +319,9 @@ static PyObject * RealTime_subtract(PyObject *s, PyObject *w) { - RealTimeObject *result = - PyObject_New(RealTimeObject, &RealTime_Type); + RealTimeObject *result = PyObject_New(RealTimeObject, &RealTime_Type); if (result == NULL) return NULL; + PyObject_Init((PyObject *)result, &RealTime_Type); result->rt = new RealTime( *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt); @@ -331,14 +359,11 @@ /* REAL-TIME TYPE OBJECT */ -#define RealTime_alloc PyType_GenericAlloc -#define RealTime_free PyObject_Del - /* Doc:: 10.3 Type Objects */ /* static */ PyTypeObject RealTime_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "vampy.RealTime", /*tp_name*/ + "vampyhost.RealTime", /*tp_name*/ sizeof(RealTimeObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ @@ -374,9 +399,9 @@ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ - RealTime_alloc, /*tp_alloc*/ + 0, /*tp_alloc*/ RealTime_new, /*tp_new*/ - RealTime_free, /*tp_free*/ + 0, /*tp_free*/ 0, /*tp_is_gc*/ };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test_realtime.py Wed Jun 24 14:11:19 2015 +0100 @@ -0,0 +1,109 @@ + +import vamp + +def test_basic_conf_compare_sec(): + r1 = vamp.vampyhost.RealTime('seconds', 0) + r2 = vamp.vampyhost.RealTime('seconds', 0) + assert r1 == r2 + r2a = vamp.vampyhost.RealTime() + assert r1 == r2a + r3 = vamp.vampyhost.RealTime('seconds', 1.5) + assert r1 != r3 + assert r2 != r3 + assert r1 < r3 + assert r3 > r2 + assert r1 <= r3 + assert r3 >= r2 + assert r1 >= r2 + +def test_basic_conf_compare_msec(): + r1 = vamp.vampyhost.RealTime('milliseconds', 0) + r2 = vamp.vampyhost.RealTime('milliseconds', 0) + assert r1 == r2 + r3 = vamp.vampyhost.RealTime('milliseconds', 1500) + assert r1 != r3 + assert r2 != r3 + assert r1 < r3 + assert r3 > r2 + assert r1 <= r3 + assert r3 >= r2 + assert r1 >= r2 + +def test_basic_conf_compare_sec_msec(): + r1 = vamp.vampyhost.RealTime('milliseconds', 0) + r2 = vamp.vampyhost.RealTime('seconds', 0) + assert r1 == r2 + r3 = vamp.vampyhost.RealTime('milliseconds', 1500) + r4 = vamp.vampyhost.RealTime('seconds', 1.5) + assert r3 == r4 + assert r1 != r3 + assert r2 != r3 + assert r1 < r3 + assert r3 > r2 + assert r1 <= r3 + assert r3 >= r2 + assert r4 >= r2 + assert r1 >= r2 + assert r4 <= r3 + +def test_basic_conf_compare_int_float(): + r1 = vamp.vampyhost.RealTime('seconds', 100) + r2 = vamp.vampyhost.RealTime('seconds', 100.0) + assert r1 == r2 + r2n = vamp.vampyhost.RealTime('seconds', 100.00001) + assert r1 != r2n + assert r2 != r2n + r1 = vamp.vampyhost.RealTime('milliseconds', 100) + r2 = vamp.vampyhost.RealTime('milliseconds', 100.0) + r2n = vamp.vampyhost.RealTime('milliseconds', 100.00001) + r3 = vamp.vampyhost.RealTime('seconds', 0.1) + assert r1 == r2 + assert r1 != r2n + assert r2 != r2n + assert r1 == r3 + assert r2 == r3 + +def test_basic_conf_compare_tuple(): + r1 = vamp.vampyhost.RealTime(0, 0) + r2 = vamp.vampyhost.RealTime(0, 0) + assert r1 == r2 + r3 = vamp.vampyhost.RealTime(1, 500000000) + r4 = vamp.vampyhost.RealTime('seconds', 1.5) + assert r3 == r4 + assert r1 != r3 + assert r2 != r3 + assert r1 < r3 + assert r3 > r2 + assert r1 <= r3 + assert r3 >= r2 + assert r4 >= r2 + assert r1 >= r2 + assert r4 <= r3 + +def test_conv_float(): + r = vamp.vampyhost.RealTime('seconds', 0) + assert float(r) == 0.0 + +def test_conv_float(): + r = vamp.vampyhost.RealTime('seconds', 0) + assert float(r) == 0.0 + +def test_conv_str(): + r = vamp.vampyhost.RealTime('seconds', 0) + assert str(r) == " 0.000000000" + r = vamp.vampyhost.RealTime('seconds', 1.5) + assert str(r) == " 1.500000000" + r = vamp.vampyhost.RealTime('seconds', -2) + assert str(r) == "-2.000000000" + r = vamp.vampyhost.RealTime(-1, -500000000) + assert str(r) == "-1.500000000" + +def test_add_subtract(): + r1 = vamp.vampyhost.RealTime('milliseconds', 400) + r2 = vamp.vampyhost.RealTime('milliseconds', 600) + r3 = vamp.vampyhost.RealTime('seconds', 1) + assert r1 + r2 == r3 + assert r3 - r2 - r1 == vamp.vampyhost.RealTime() + assert r2 - r1 == vamp.vampyhost.RealTime('milliseconds', 200) + assert r1 - r2 == vamp.vampyhost.RealTime('milliseconds', -200) +
--- a/vamp/__init__.py Wed Jun 24 10:50:13 2015 +0100 +++ b/vamp/__init__.py Wed Jun 24 14:11:19 2015 +0100 @@ -28,8 +28,11 @@ # dealings in this Software without prior written authorization. '''Load and use Vamp plugins for audio feature analysis. This module -is a high-level interface to the vampyhost extension, for quickly and -easily running Vamp analysis plugins on buffers of audio data.''' +is a high-level interface wrapper around a native-code extension, for +quickly and easily running Vamp analysis plugins on buffers of audio +data. For low-level plugin loading and manipulation, refer to the +vamp.vampyhost namespace which contains the native-code extension. +''' import vampyhost