summaryrefslogtreecommitdiff
path: root/pysoundtouch/src/pybpmdetect.cpp
diff options
context:
space:
mode:
authoryo mama <pepper@scannerjammer.com>2015-06-19 16:24:27 -0400
committeryo mama <pepper@scannerjammer.com>2015-06-19 16:24:27 -0400
commit8adfb3bd99b4dcff2459756af090a640fd7a4b4a (patch)
treec1e6adddda335f4d36a98039ccc5ac867ae7296d /pysoundtouch/src/pybpmdetect.cpp
clone
Diffstat (limited to 'pysoundtouch/src/pybpmdetect.cpp')
-rw-r--r--pysoundtouch/src/pybpmdetect.cpp122
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);
+}