diff options
| author | yo mama <pepper@scannerjammer.com> | 2015-06-19 16:24:27 -0400 |
|---|---|---|
| committer | yo mama <pepper@scannerjammer.com> | 2015-06-19 16:24:27 -0400 |
| commit | 8adfb3bd99b4dcff2459756af090a640fd7a4b4a (patch) | |
| tree | c1e6adddda335f4d36a98039ccc5ac867ae7296d /pysoundtouch/src/pybpmdetect.cpp | |
clone
Diffstat (limited to 'pysoundtouch/src/pybpmdetect.cpp')
| -rw-r--r-- | pysoundtouch/src/pybpmdetect.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/pysoundtouch/src/pybpmdetect.cpp b/pysoundtouch/src/pybpmdetect.cpp new file mode 100644 index 0000000..03a673f --- /dev/null +++ b/pysoundtouch/src/pybpmdetect.cpp @@ -0,0 +1,122 @@ +/* + * python interface to soundtouch (the open-source audio processing library) + * + * The structure of this code was based on pymad-0.5.4 + * This is a C++ file. + */ + +#include <Python.h> + +extern "C" { + #include "soundtouchmodule.h" +} +#include "pybpmdetect.h" + +#if PY_VERSION_HEX < 0x01060000 +#define PyObject_DEL(op) PyMem_DEL((op)) +#endif + +PyTypeObject py_bpmdetect_t = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "BPMDetect", + sizeof(py_bpmdetect), + 0, + /* standard methods */ + (destructor) py_bpmdetect_dealloc, + (printfunc) 0, + (getattrfunc) py_bpmdetect_getattr, + (setattrfunc) 0, + (cmpfunc) 0, + (reprfunc) 0, + /* type categories */ + 0, /* as number */ + 0, /* as sequence */ + 0, /* as mapping */ + 0, /* hash */ + 0, /* binary */ + 0, /* repr */ + 0, /* getattro */ + 0, /* setattro */ + 0, /* as buffer */ + 0, /* tp_flags */ + NULL +}; + +// Constructor +PyObject* py_bpmdetect_new(PyObject* self, PyObject* args) { + py_bpmdetect* ps = NULL; + uint sampleRate, channels; + + // Needs to be constructed with sampling rate and number of channels + if (!PyArg_ParseTuple(args, "II:Soundtouch", &sampleRate, &channels)) { + PyErr_SetString(PyExc_RuntimeError, "Requires sampling rate and number of channels (sample size must be 2)"); + return NULL; + } + + // Create the object + ps = PyObject_NEW(py_bpmdetect, &py_bpmdetect_t); + ps->bpmdetect = new soundtouch::BPMDetect((int) channels, (int) sampleRate); + ps->channels = (int) channels; + + return (PyObject*) ps; +} + +// Deallocate the BPMDetect object +static void py_bpmdetect_dealloc(PyObject* self, PyObject* args) { + py_bpmdetect* ps = PY_BPMDETECT(self); + + if (ps->bpmdetect) { + delete ps->bpmdetect; + ps->bpmdetect = NULL; + } + + PyObject_DEL(self); +} + +// Read in a number of samples for beat detection +static PyObject* py_bpmdetect_put_samples(PyObject* self, PyObject* args) { + py_bpmdetect* ps = PY_BPMDETECT(self); + int buflen; + char* transfer; + + // Needs to be called with a string of samples + if (!PyArg_ParseTuple(args, "s#", &transfer, &buflen)) { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return NULL; + } + + // Move all into our char-short union + for (int ii = 0; ii < buflen; ii++) + ps->buffer.chars[ii] = transfer[ii]; + + // Input them into the BMP detector + ps->bpmdetect->inputSamples(ps->buffer.shorts, (uint) buflen / (2 * ps->channels)); + + Py_INCREF(Py_None); + return Py_None; +} + +// Perform the beat detection algorithm +// return the beats per minute +static PyObject* py_bpmdetect_get_bpm(PyObject* self, PyObject* args) { + py_bpmdetect* ps = PY_BPMDETECT(self); + + // Return the BPM of the input samples + float bpm = ps->bpmdetect->getBpm(); + + return PyFloat_FromDouble(bpm); +} + +/* housekeeping */ + +static PyMethodDef bpmdetect_methods[] = { + { "put_samples", py_bpmdetect_put_samples, METH_VARARGS, "" }, + { "get_bpm", py_bpmdetect_get_bpm, METH_VARARGS, "" }, + { NULL, 0, 0, NULL } +}; + +// Extract information from the bpmdetect object +static PyObject* py_bpmdetect_getattr(PyObject* self, char* name) { + return Py_FindMethod(bpmdetect_methods, self, name); +} |
