annotate pyRealTime.cpp @ 11:e5b575d69b01 lf-numpy-arrays

changed a comment
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Wed, 20 Mar 2013 11:07:24 +0000
parents cb0d3af1be4d
children
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2 /*
Chris@0 3
Chris@0 4 This module exposes a Type Object wrapping Vamp::RealTime
Chris@0 5 together with module level functions to create
Chris@0 6 new pyRealTime objects from frame count, samplerate or sec,nsec tuples.
Chris@0 7
Chris@0 8 A small API is provided for the C/C++ programmer and relevant
Chris@0 9 functions are exposed to Python.
Chris@0 10
Chris@0 11 TODO: implement number protocol (i.e. wrap arithmetic operators)
Chris@0 12 partly done
Chris@0 13
Chris@0 14 */
Chris@0 15
Chris@0 16 #include <Python.h>
Chris@0 17 #include <pyRealTime.h>
Chris@1 18 #include "vamp-hostsdk/Plugin.h"
Chris@0 19 #include <string>
Chris@0 20
Chris@0 21 using namespace std;
Chris@0 22 using namespace Vamp;
Chris@0 23
Chris@0 24 using Vamp::Plugin;
Chris@0 25 using Vamp::RealTime;
Chris@0 26
Chris@0 27 /* REAL-TIME TYPE OBJECT */
Chris@0 28
Chris@0 29
Chris@0 30 /* Documentation for our new module */
Chris@0 31 PyDoc_STRVAR(module_doc,
Chris@0 32 "This module is a thin wrapper around Vamp::RealTime.");
Chris@0 33
Chris@0 34
Chris@0 35 /* RealTime Object's Methods */
Chris@0 36 //Note: these are internals, not exposed by the module but the object
Chris@0 37
Chris@0 38 /* Returns a Tuple containing sec and nsec values */
Chris@0 39 static PyObject *
Chris@0 40 RealTime_values(RealTimeObject *self)
Chris@0 41 {
Chris@0 42 return Py_BuildValue("(ii)",
Chris@0 43 self->rt->sec,self->rt->nsec);
Chris@0 44 }
Chris@0 45
Chris@0 46 /* Returns a Text representation */
Chris@0 47 static PyObject *
Chris@0 48 RealTime_toText(RealTimeObject *self, PyObject *args)
Chris@0 49 {
Chris@0 50 return Py_BuildValue("s",
Chris@0 51 self->rt->toText().c_str());
Chris@0 52 }
Chris@0 53
Chris@0 54 /* String representation called by e.g. str(realtime), print realtime*/
Chris@0 55 static PyObject *
Chris@0 56 RealTime_repr(PyObject *self)
Chris@0 57 {
Chris@0 58 return Py_BuildValue("s",
Chris@0 59 ((RealTimeObject*)self)->rt->toString().c_str());
Chris@0 60 }
Chris@0 61
Chris@0 62
Chris@0 63 /* Frame representation */
Chris@0 64 static PyObject *
Chris@0 65 RealTime_toFrame(PyObject *self, PyObject *args)
Chris@0 66 {
Chris@0 67 unsigned int samplerate;
Chris@0 68
Chris@0 69 if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ",
Chris@0 70 (unsigned int *) &samplerate )) {
Chris@0 71 PyErr_SetString(PyExc_ValueError,
Chris@0 72 "Sample Rate Required.");
Chris@0 73 return NULL;
Chris@0 74 }
Chris@0 75
Chris@0 76 return Py_BuildValue("k",
Chris@0 77 RealTime::realTime2Frame(
Chris@0 78 *(const RealTime*) ((RealTimeObject*)self)->rt,
Chris@0 79 (unsigned int) samplerate));
Chris@0 80 }
Chris@0 81
Chris@0 82 /* Conversion of realtime to a double precision floating point value */
Chris@0 83 /* ...in Python called by e.g. float(realtime) */
Chris@0 84 static PyObject *
Chris@0 85 RealTime_float(PyObject *s)
Chris@0 86 {
Chris@0 87 double drt = ((double) ((RealTimeObject*)s)->rt->sec +
Chris@0 88 (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
Chris@0 89 return PyFloat_FromDouble(drt);
Chris@0 90 }
Chris@0 91
Chris@0 92 /* test */
Chris@0 93 static PyObject *
Chris@0 94 RealTime_test(PyObject *self)
Chris@0 95 {
Chris@0 96
Chris@0 97 long frame = 100;
Chris@0 98 unsigned int sampleRate = 22050;
Chris@0 99
Chris@0 100 const RealTime t = RealTime::frame2RealTime(frame,sampleRate);
Chris@0 101 long back = RealTime::realTime2Frame(t,sampleRate);
Chris@0 102 cerr << "Reverse Conversion: " << back << endl;
Chris@0 103
Chris@0 104 return Py_BuildValue("s",
Chris@0 105 ((RealTimeObject*)self)->rt->toString().c_str());
Chris@0 106 }
Chris@0 107
Chris@0 108
Chris@0 109 /* Type object's (RealTime) methods table */
Chris@0 110 static PyMethodDef RealTime_methods[] = {
Chris@0 111
Chris@0 112 {"toText", (PyCFunction)RealTime_toText, METH_NOARGS,
Chris@0 113 PyDoc_STR("toText() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
Chris@0 114
Chris@0 115 {"values", (PyCFunction)RealTime_values, METH_NOARGS,
Chris@0 116 PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
Chris@0 117
Chris@0 118 {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS,
Chris@0 119 PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
Chris@0 120
Chris@0 121 {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS,
Chris@0 122 PyDoc_STR("float() -> Floating point representation.")},
Chris@0 123
Chris@0 124 {"test", (PyCFunction)RealTime_test, METH_VARARGS,
Chris@0 125 PyDoc_STR("test() -> .")},
Chris@0 126
Chris@0 127 {NULL, NULL} /* sentinel */
Chris@0 128 };
Chris@0 129
Chris@0 130
Chris@0 131
Chris@0 132 /* Function to set basic attributes */
Chris@0 133 static int
Chris@0 134 RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
Chris@0 135 {
Chris@0 136
Chris@0 137 if ( !string(name).compare("sec")) {
Chris@0 138 self->rt->sec= (int) PyInt_AS_LONG(value);
Chris@0 139 return 0;
Chris@0 140 }
Chris@0 141
Chris@0 142 if ( !string(name).compare("nsec")) {
Chris@0 143 self->rt->nsec= (int) PyInt_AS_LONG(value);
Chris@0 144 return 0;
Chris@0 145 }
Chris@0 146
Chris@0 147 return -1;
Chris@0 148 }
Chris@0 149
Chris@0 150 /* Function to get basic attributes */
Chris@0 151 static PyObject *
Chris@0 152 RealTime_getattr(RealTimeObject *self, char *name)
Chris@0 153 {
Chris@0 154
Chris@0 155 if ( !string(name).compare("sec") ) {
Chris@0 156 return PyInt_FromSsize_t(
Chris@0 157 (Py_ssize_t) self->rt->sec);
Chris@0 158 }
Chris@0 159
Chris@0 160 if ( !string(name).compare("nsec") ) {
Chris@0 161 return PyInt_FromSsize_t(
Chris@0 162 (Py_ssize_t) self->rt->nsec);
Chris@0 163 }
Chris@0 164
Chris@0 165 return Py_FindMethod(RealTime_methods,
Chris@0 166 (PyObject *)self, name);
Chris@0 167 }
Chris@0 168
Chris@0 169
Chris@0 170 /* DESTRUCTOR: delete type object */
Chris@0 171 static void
Chris@0 172 RealTimeObject_dealloc(RealTimeObject *self)
Chris@0 173 {
Chris@0 174 delete self->rt; //delete the C object
Chris@0 175 PyObject_Del(self); //delete the Python object
Chris@0 176 }
Chris@0 177
Chris@0 178 /* Number Protocol */
Chris@0 179
Chris@0 180
Chris@0 181 static PyObject *
Chris@0 182 RealTime_add(PyObject *s, PyObject *w)
Chris@0 183 {
Chris@0 184
Chris@0 185 RealTimeObject *result =
Chris@0 186 PyObject_New(RealTimeObject, &RealTime_Type);
Chris@0 187 if (result == NULL) return NULL;
Chris@0 188
Chris@1 189 result->rt = new RealTime(
Chris@0 190 *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
Chris@0 191 return (PyObject*)result;
Chris@0 192 }
Chris@0 193
Chris@0 194 static PyObject *
Chris@0 195 RealTime_subtract(PyObject *s, PyObject *w)
Chris@0 196 {
Chris@0 197
Chris@0 198 RealTimeObject *result =
Chris@0 199 PyObject_New(RealTimeObject, &RealTime_Type);
Chris@0 200 if (result == NULL) return NULL;
Chris@0 201
Chris@1 202 result->rt = new RealTime(
Chris@0 203 *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
Chris@0 204 return (PyObject*)result;
Chris@0 205 }
Chris@0 206
Chris@0 207
Chris@0 208 static PyNumberMethods realtime_as_number = {
Chris@0 209 RealTime_add, /*nb_add*/
Chris@0 210 RealTime_subtract, /*nb_subtract*/
Chris@0 211 0, /*nb_multiply*/
Chris@0 212 0, /*nb_divide*/
Chris@0 213 0, /*nb_remainder*/
Chris@0 214 0, /*nb_divmod*/
Chris@0 215 0, /*nb_power*/
Chris@0 216 0, /*nb_neg*/
Chris@0 217 0, /*nb_pos*/
Chris@0 218 0, /*(unaryfunc)array_abs,*/
Chris@0 219 0, /*nb_nonzero*/
Chris@0 220 0, /*nb_invert*/
Chris@0 221 0, /*nb_lshift*/
Chris@0 222 0, /*nb_rshift*/
Chris@0 223 0, /*nb_and*/
Chris@0 224 0, /*nb_xor*/
Chris@0 225 0, /*nb_or*/
Chris@0 226 0, /*nb_coerce*/
Chris@0 227 0, /*nb_int*/
Chris@0 228 0, /*nb_long*/
Chris@0 229 (unaryfunc)RealTime_float, /*nb_float*/
Chris@0 230 0, /*nb_oct*/
Chris@0 231 0, /*nb_hex*/
Chris@0 232 };
Chris@0 233
Chris@0 234 /* pyRealTime TypeObject */
Chris@0 235
Chris@0 236
Chris@0 237 /* Doc:: 10.3 Type Objects */
Chris@0 238 /* static */ PyTypeObject RealTime_Type = {
Chris@0 239 /* The ob_type field must be initialized in the module init function
Chris@0 240 * to be portable to Windows without using C++. */
Chris@0 241 PyObject_HEAD_INIT(NULL)
Chris@0 242 0, /*ob_size*/
Chris@0 243 "pyRealTime.realtime", /*tp_name*/
Chris@0 244 sizeof(RealTimeObject), /*tp_basicsize*/
Chris@0 245 sizeof(RealTime), /*tp_itemsize*/
Chris@0 246 /* methods */
Chris@0 247 (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
Chris@0 248 0, /*tp_print*/
Chris@0 249 (getattrfunc)RealTime_getattr, /*tp_getattr*/
Chris@0 250 (setattrfunc)RealTime_setattr, /*tp_setattr*/
Chris@0 251 0, /*tp_compare*/
Chris@0 252 RealTime_repr, /*tp_repr*/
Chris@0 253 &realtime_as_number, /*tp_as_number*/
Chris@0 254 0, /*tp_as_sequence*/
Chris@0 255 0, /*tp_as_mapping*/
Chris@0 256 0, /*tp_hash*/
Chris@0 257 0,//(ternaryfunc)RealTime_new, /*tp_call*/
Chris@0 258 0, /*tp_str*/
Chris@0 259 0, /*tp_getattro*/
Chris@0 260 0, /*tp_setattro*/
Chris@0 261 0, /*tp_as_buffer*/
Chris@0 262 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Chris@0 263 0, /*tp_doc*/
Chris@0 264 0, /*tp_traverse*/
Chris@0 265 0, /*tp_clear*/
Chris@0 266 0, /*tp_richcompare*/
Chris@0 267 0, /*tp_weaklistoffset*/
Chris@0 268 0, /*tp_iter*/
Chris@0 269 0, /*tp_iternext*/
Chris@0 270 RealTime_methods, /*tp_methods*/ //TypeObject Methods
Chris@0 271 0, /*tp_members*/
Chris@0 272 0, /*tp_getset*/
Chris@0 273 0, /*tp_base*/
Chris@0 274 0, /*tp_dict*/
Chris@0 275 0, /*tp_descr_get*/
Chris@0 276 0, /*tp_descr_set*/
Chris@0 277 0, /*tp_dictoffset*/
Chris@0 278 0, /*tp_init*/
Chris@0 279 0, /*tp_alloc*/
Chris@0 280 0, /*tp_new*/
Chris@0 281 0, /*tp_free*/
Chris@0 282 0, /*tp_is_gc*/
Chris@0 283 };
Chris@0 284
Chris@0 285
Chris@0 286 /* Remaining Functions Exposed by the MODULE */
Chris@0 287
Chris@0 288
Chris@0 289 /* New RealTime object from Frame (with given samplerate) */
Chris@0 290 /*static*/ PyObject *
Chris@0 291 RealTime_frame2RealTime(PyObject *ignored, PyObject *args)
Chris@0 292 {
Chris@0 293
Chris@0 294 long frame;
Chris@0 295 unsigned int sampleRate;
Chris@0 296
Chris@0 297 if (!PyArg_ParseTuple(args, "lI:realtime.fame2RealTime ",
Chris@0 298 &frame,
Chris@0 299 &sampleRate))
Chris@0 300 return NULL;
Chris@0 301 /*Doc:: 5.5 Parsing arguments and building values*/
Chris@0 302
Chris@0 303 RealTimeObject *self;
Chris@0 304 self = PyObject_New(RealTimeObject, &RealTime_Type);
Chris@0 305 if (self == NULL)
Chris@0 306 return NULL;
Chris@0 307
Chris@1 308 self->rt = new RealTime(
Chris@0 309 RealTime::frame2RealTime(frame,sampleRate));
Chris@0 310
Chris@0 311 return (PyObject *) self;
Chris@0 312 }
Chris@0 313
Chris@0 314 /* New RealTime object from sec and nsec */
Chris@0 315 /*static*/ PyObject *
Chris@0 316 RealTime_new(PyObject *ignored, PyObject *args)
Chris@0 317 {
Chris@0 318
Chris@0 319 unsigned int sec = 0;
Chris@0 320 unsigned int nsec = 0;
Chris@0 321 double unary = 0;
Chris@0 322 const char *fmt = NULL;
Chris@0 323
Chris@0 324 /*Doc:: 5.5 Parsing arguments and building values*/
Chris@0 325 if (
Chris@0 326
Chris@0 327 !PyArg_ParseTuple(args, "|sd:realtime.new ",
Chris@0 328 (const char *) &fmt,
Chris@0 329 (double *) &unary) &&
Chris@0 330
Chris@0 331 !PyArg_ParseTuple(args, "|II:realtime.new ",
Chris@0 332 (unsigned int*) &sec,
Chris@0 333 (unsigned int*) &nsec)
Chris@0 334
Chris@0 335 ) {
Chris@0 336 PyErr_SetString(PyExc_TypeError,
Chris@0 337 "RealTime initialised with wrong arguments.");
Chris@0 338 return NULL; }
Chris@0 339
Chris@0 340 PyErr_Clear();
Chris@0 341
Chris@0 342 RealTimeObject *self =
Chris@0 343 PyObject_New(RealTimeObject, &RealTime_Type);
Chris@0 344 if (self == NULL) return NULL;
Chris@0 345
Chris@0 346 self->rt = NULL;
Chris@0 347
Chris@0 348 if (sec == 0 && nsec == 0 && fmt == 0)
Chris@1 349 self->rt = new RealTime();
Chris@0 350 else if (fmt == 0)
Chris@1 351 self->rt = new RealTime(sec,nsec);
Chris@0 352 else {
Chris@0 353
Chris@0 354 if (!string(fmt).compare("float") ||
Chris@0 355 !string(fmt).compare("seconds"))
Chris@1 356 self->rt = new RealTime(
Chris@0 357 RealTime::fromSeconds((double) unary));
Chris@0 358
Chris@0 359 if (!string(fmt).compare("milliseconds")) {
Chris@1 360 self->rt = new RealTime(
Chris@0 361 RealTime::fromSeconds((double) unary / 1000.0)); }
Chris@0 362 }
Chris@0 363
Chris@0 364 if (!self->rt) {
Chris@0 365 PyErr_SetString(PyExc_TypeError,
Chris@0 366 "RealTime initialised with wrong arguments.");
Chris@0 367 return NULL;
Chris@0 368 }
Chris@0 369
Chris@0 370 return (PyObject *) self;
Chris@0 371 }
Chris@0 372
Chris@0 373
Chris@0 374 /* pyRealTime Module's methods table */
Chris@0 375 static PyMethodDef Module_methods[] = {
Chris@0 376
Chris@0 377 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
Chris@0 378 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
Chris@0 379
Chris@0 380 {"realtime", RealTime_new, METH_VARARGS,
Chris@0 381 PyDoc_STR("realtime() -> returns new RealTime object")},
Chris@0 382
Chris@0 383 {NULL, NULL} /* sentinel */
Chris@0 384 };
Chris@0 385
Chris@0 386
Chris@0 387 /* PyRealTime C API functions */
Chris@0 388
Chris@0 389
Chris@0 390
Chris@0 391 /*RealTime from PyRealTime*/
Chris@0 392 RealTime*
Chris@0 393 PyRealTime_AsPointer (PyObject *self) {
Chris@0 394
Chris@0 395 RealTimeObject *s = (RealTimeObject*) self;
Chris@0 396
Chris@0 397 if (!PyRealTime_Check(s)) {
Chris@0 398 PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
Chris@0 399 cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
Chris@0 400 return NULL; }
Chris@0 401 return s->rt; };
Chris@0 402
Chris@0 403 /*PyRealTime from RealTime*/
Chris@0 404 PyObject*
Chris@0 405 PyRealTime_FromRealTime(Vamp::RealTime *rt) {
Chris@0 406
Chris@0 407 RealTimeObject *self =
Chris@0 408 PyObject_New(RealTimeObject, &RealTime_Type);
Chris@0 409 if (self == NULL) return NULL;
Chris@0 410
Chris@1 411 self->rt = new RealTime(*rt);
Chris@0 412 return (PyObject*) self;
Chris@0 413 //TODO: check if we need to INCREF here
Chris@0 414 }
Chris@0 415
Chris@0 416
Chris@0 417 /* Module initialization (includes extern "C" {...}) */
Chris@0 418 PyMODINIT_FUNC
Chris@0 419 initpyRealTime(void)
Chris@0 420 {
Chris@0 421 PyObject *m;
Chris@0 422
Chris@0 423 /* Finalize the type object including setting type of the new type
Chris@0 424 * object; doing it here is required for portability to Windows
Chris@0 425 * without requiring C++. */
Chris@0 426 if (PyType_Ready(&RealTime_Type) < 0)
Chris@0 427 return;
Chris@0 428
Chris@0 429 /* Create the module and add the functions */
Chris@0 430 m = Py_InitModule3("pyRealTime", Module_methods, module_doc);
Chris@0 431 if (m == NULL)
Chris@0 432 return;
Chris@0 433
Chris@0 434 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
Chris@0 435
Chris@0 436 }