annotate modules-and-plug-ins/python-module/btrack_python_module.cpp @ 54:9699024bb3d0

Before this commit, the OnsetDetectionFunction class used double precision, and the BTrack class used floats. I have now made BTrack use double precision also. This works fine and the only cost of doing this is that we have to perform one array copy into floating point format so that sample rate conversion (which has to be in floating point format) can take place.
author Adam Stark <adamstark@users.noreply.github.com>
date Wed, 22 Jan 2014 02:49:29 +0000
parents 45231107c9d6
children 450c53430540
rev   line source
adamstark@51 1 #include <iostream>
adamstark@51 2 #include <Python.h>
adamstark@51 3 #include "../../src/OnsetDetectionFunction.h"
adamstark@51 4 #include "../../src/BTrack.h"
adamstark@51 5 #include <numpy/arrayobject.h>
adamstark@51 6
adamstark@51 7 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args)
adamstark@51 8 {
adamstark@51 9 PyObject *arg1=NULL;
adamstark@51 10 PyObject *arr1=NULL;
adamstark@51 11
adamstark@51 12 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 13 {
adamstark@51 14 return NULL;
adamstark@51 15 }
adamstark@51 16
adamstark@51 17 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 18 if (arr1 == NULL)
adamstark@51 19 {
adamstark@51 20 return NULL;
adamstark@51 21 }
adamstark@51 22
adamstark@51 23
adamstark@51 24
adamstark@51 25 ////////// GET INPUT DATA ///////////////////
adamstark@51 26
adamstark@51 27 // get data as array
adamstark@51 28 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 29
adamstark@51 30 // get array size
adamstark@52 31 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@51 32 //int k = (int) theSize;
adamstark@51 33
adamstark@51 34 // get data type
adamstark@52 35 //char type = PyArray_DESCR(arr1)->type;
adamstark@51 36
adamstark@51 37 ////////// BEGIN PROCESS ///////////////////
adamstark@51 38 int hsize = 512;
adamstark@51 39 int fsize = 1024;
adamstark@51 40 int df_type = 6;
adamstark@51 41 int numframes;
adamstark@51 42 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples
adamstark@51 43
adamstark@51 44
adamstark@51 45 // get number of audio frames, given the hop size and signal length
adamstark@51 46 numframes = (int) floor(((double) signal_length) / ((double) hsize));
adamstark@51 47
adamstark@51 48 OnsetDetectionFunction onset(hsize,fsize,df_type,1);
adamstark@51 49
adamstark@51 50 double df[numframes];
adamstark@51 51
adamstark@51 52
adamstark@51 53
adamstark@51 54 ///////////////////////////////////////////
adamstark@51 55 //////// Begin Processing Loop ////////////
adamstark@51 56
adamstark@51 57 for (int i=0;i < numframes;i++)
adamstark@51 58 {
adamstark@51 59 // add new samples to frame
adamstark@51 60 for (int n = 0;n < hsize;n++)
adamstark@51 61 {
adamstark@51 62 buffer[n] = data[(i*hsize)+n];
adamstark@51 63 }
adamstark@51 64
adamstark@51 65 df[i] = onset.getDFsample(buffer);
adamstark@51 66
adamstark@51 67 }
adamstark@51 68
adamstark@51 69 ///////// End Processing Loop /////////////
adamstark@51 70 ///////////////////////////////////////////
adamstark@51 71
adamstark@51 72
adamstark@51 73 ////////// END PROCESS ///////////////////
adamstark@51 74
adamstark@51 75
adamstark@51 76
adamstark@51 77 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 78 int nd=1;
adamstark@51 79 npy_intp m= numframes;
adamstark@51 80 //double fArray[5] = {0,1,2,3,4};
adamstark@51 81
adamstark@51 82 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 83
adamstark@51 84 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 85
adamstark@51 86 memcpy(arr_data, df, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 87
adamstark@51 88
adamstark@51 89 Py_DECREF(arr1);
adamstark@51 90 Py_INCREF(Py_None);
adamstark@51 91 //return Py_None;
adamstark@51 92
adamstark@51 93 return (PyObject *)c;
adamstark@51 94
adamstark@51 95 //return Py_BuildValue("c", type);
adamstark@51 96 //return Py_BuildValue("d", sum);
adamstark@51 97 //return Py_BuildValue("i", k);
adamstark@51 98 /*
adamstark@51 99 fail:
adamstark@51 100 Py_XDECREF(arr1);
adamstark@51 101 Py_XDECREF(arr2);
adamstark@51 102 PyArray_XDECREF_ERR(oarr);
adamstark@51 103 return NULL;*/
adamstark@51 104 }
adamstark@51 105
adamstark@51 106
adamstark@51 107 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args)
adamstark@51 108 {
adamstark@51 109 PyObject *arg1=NULL;
adamstark@51 110 PyObject *arr1=NULL;
adamstark@51 111
adamstark@51 112 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 113 {
adamstark@51 114 return NULL;
adamstark@51 115 }
adamstark@51 116
adamstark@51 117 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 118 if (arr1 == NULL)
adamstark@51 119 {
adamstark@51 120 return NULL;
adamstark@51 121 }
adamstark@51 122
adamstark@51 123
adamstark@51 124
adamstark@51 125 ////////// GET INPUT DATA ///////////////////
adamstark@51 126
adamstark@51 127 // get data as array
adamstark@51 128 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 129
adamstark@51 130 // get array size
adamstark@52 131 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@51 132 //int k = (int) theSize;
adamstark@51 133
adamstark@51 134 // get data type
adamstark@52 135 //char type = PyArray_DESCR(arr1)->type;
adamstark@51 136
adamstark@51 137 ////////// BEGIN PROCESS ///////////////////
adamstark@51 138 int hsize = 512;
adamstark@51 139 int fsize = 1024;
adamstark@51 140 int df_type = 6;
adamstark@51 141 int numframes;
adamstark@51 142 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples
adamstark@51 143
adamstark@51 144
adamstark@51 145 // get number of audio frames, given the hop size and signal length
adamstark@51 146 numframes = (int) floor(((double) signal_length) / ((double) hsize));
adamstark@51 147
adamstark@51 148 OnsetDetectionFunction onset(hsize,fsize,df_type,1);
adamstark@51 149 BTrack b;
adamstark@51 150
adamstark@51 151 b.initialise((int) hsize); // initialise beat tracker
adamstark@51 152
adamstark@51 153 // set parameters
adamstark@51 154 //b.setparams(0.9,5);
adamstark@51 155
adamstark@51 156 double df[numframes];
adamstark@51 157 double beats[5000];
adamstark@51 158 int beatnum = 0;
adamstark@54 159
adamstark@54 160 double df_val;
adamstark@51 161
adamstark@51 162 ///////////////////////////////////////////
adamstark@51 163 //////// Begin Processing Loop ////////////
adamstark@51 164
adamstark@51 165 for (int i=0;i < numframes;i++)
adamstark@51 166 {
adamstark@51 167 // add new samples to frame
adamstark@51 168 for (int n = 0;n < hsize;n++)
adamstark@51 169 {
adamstark@51 170 buffer[n] = data[(i*hsize)+n];
adamstark@51 171 }
adamstark@51 172
adamstark@51 173 df[i] = onset.getDFsample(buffer);
adamstark@51 174
adamstark@54 175 df_val = df[i] + 0.0001;
adamstark@51 176
adamstark@51 177 b.process(df_val); // process df sample in beat tracker
adamstark@51 178
adamstark@51 179 if (b.playbeat == 1)
adamstark@51 180 {
adamstark@51 181 beats[beatnum] = (((double) hsize) / 44100) * ((double) i);
adamstark@51 182 beatnum = beatnum + 1;
adamstark@51 183 }
adamstark@51 184
adamstark@51 185 }
adamstark@51 186
adamstark@51 187 ///////// End Processing Loop /////////////
adamstark@51 188 ///////////////////////////////////////////
adamstark@51 189
adamstark@51 190
adamstark@51 191 ////////// END PROCESS ///////////////////
adamstark@51 192
adamstark@51 193 double beats_out[beatnum]; // create output array
adamstark@51 194
adamstark@51 195 // copy beats into output array
adamstark@51 196 for (int i = 0;i < beatnum;i++)
adamstark@51 197 {
adamstark@51 198 beats_out[i] = beats[i];
adamstark@51 199 }
adamstark@51 200
adamstark@51 201
adamstark@51 202
adamstark@51 203 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 204 int nd=1;
adamstark@51 205 npy_intp m= beatnum;
adamstark@51 206 //double fArray[5] = {0,1,2,3,4};
adamstark@51 207
adamstark@51 208 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 209
adamstark@51 210 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 211
adamstark@51 212 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 213
adamstark@51 214
adamstark@51 215 Py_DECREF(arr1);
adamstark@51 216 Py_INCREF(Py_None);
adamstark@51 217 //return Py_None;
adamstark@51 218
adamstark@51 219 return (PyObject *)c;
adamstark@51 220
adamstark@51 221 //return Py_BuildValue("c", type);
adamstark@51 222 //return Py_BuildValue("d", sum);
adamstark@51 223 //return Py_BuildValue("i", k);
adamstark@51 224 /*
adamstark@51 225 fail:
adamstark@51 226 Py_XDECREF(arr1);
adamstark@51 227 Py_XDECREF(arr2);
adamstark@51 228 PyArray_XDECREF_ERR(oarr);
adamstark@51 229 return NULL;*/
adamstark@51 230 }
adamstark@51 231
adamstark@51 232 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args)
adamstark@51 233 {
adamstark@51 234 PyObject *arg1=NULL;
adamstark@51 235 PyObject *arr1=NULL;
adamstark@51 236
adamstark@51 237 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 238 {
adamstark@51 239 return NULL;
adamstark@51 240 }
adamstark@51 241
adamstark@51 242 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 243 if (arr1 == NULL)
adamstark@51 244 {
adamstark@51 245 return NULL;
adamstark@51 246 }
adamstark@51 247
adamstark@51 248
adamstark@51 249
adamstark@51 250 ////////// GET INPUT DATA ///////////////////
adamstark@51 251
adamstark@51 252 // get data as array
adamstark@51 253 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 254
adamstark@51 255 // get array size
adamstark@52 256 long numframes = PyArray_Size((PyObject*)arr1);
adamstark@51 257 //int k = (int) theSize;
adamstark@51 258
adamstark@51 259 // get data type
adamstark@52 260 //char type = PyArray_DESCR(arr1)->type;
adamstark@51 261
adamstark@51 262 ////////// BEGIN PROCESS ///////////////////
adamstark@51 263 int hsize = 512;
adamstark@51 264
adamstark@51 265 BTrack b;
adamstark@51 266
adamstark@51 267 b.initialise((int) hsize); // initialise beat tracker
adamstark@51 268
adamstark@51 269 // set parameters
adamstark@51 270 //b.setparams(0.9,5);
adamstark@51 271
adamstark@51 272 double beats[5000];
adamstark@51 273 int beatnum = 0;
adamstark@54 274 double df_val;
adamstark@51 275
adamstark@51 276 ///////////////////////////////////////////
adamstark@51 277 //////// Begin Processing Loop ////////////
adamstark@51 278
adamstark@52 279 for (long i=0;i < numframes;i++)
adamstark@51 280 {
adamstark@54 281 df_val = data[i] + 0.0001;
adamstark@51 282
adamstark@51 283 b.process(df_val); // process df sample in beat tracker
adamstark@51 284
adamstark@51 285 if (b.playbeat == 1)
adamstark@51 286 {
adamstark@51 287 beats[beatnum] = (((double) hsize) / 44100) * ((double) i);
adamstark@51 288 beatnum = beatnum + 1;
adamstark@51 289 }
adamstark@51 290
adamstark@51 291 }
adamstark@51 292
adamstark@51 293 ///////// End Processing Loop /////////////
adamstark@51 294 ///////////////////////////////////////////
adamstark@51 295
adamstark@51 296
adamstark@51 297 ////////// END PROCESS ///////////////////
adamstark@51 298
adamstark@51 299 double beats_out[beatnum]; // create output array
adamstark@51 300
adamstark@51 301
adamstark@51 302 // copy beats into output array
adamstark@51 303 for (int i = 0;i < beatnum;i++)
adamstark@51 304 {
adamstark@51 305 beats_out[i] = beats[i];
adamstark@51 306 }
adamstark@51 307
adamstark@51 308
adamstark@51 309 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 310 int nd=1;
adamstark@51 311 npy_intp m= beatnum;
adamstark@51 312 //double fArray[5] = {0,1,2,3,4};
adamstark@51 313
adamstark@51 314 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 315
adamstark@51 316 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 317
adamstark@51 318 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 319
adamstark@51 320
adamstark@51 321 Py_DECREF(arr1);
adamstark@51 322 Py_INCREF(Py_None);
adamstark@51 323 //return Py_None;
adamstark@51 324
adamstark@51 325 return (PyObject *)c;
adamstark@51 326
adamstark@51 327 //return Py_BuildValue("c", type);
adamstark@51 328 //return Py_BuildValue("d", sum);
adamstark@51 329 //return Py_BuildValue("i", k);
adamstark@51 330 /*
adamstark@51 331 fail:
adamstark@51 332 Py_XDECREF(arr1);
adamstark@51 333 Py_XDECREF(arr2);
adamstark@51 334 PyArray_XDECREF_ERR(oarr);
adamstark@51 335 return NULL;*/
adamstark@51 336 }
adamstark@51 337
adamstark@51 338
adamstark@51 339
adamstark@51 340 static PyMethodDef btrack_methods[] = {
adamstark@51 341 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"},
adamstark@51 342 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"},
adamstark@51 343 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"},
adamstark@51 344 {NULL, NULL, 0, NULL} /* Sentinel */
adamstark@51 345 };
adamstark@51 346
adamstark@51 347 PyMODINIT_FUNC initbtrack(void)
adamstark@51 348 {
adamstark@51 349 (void)Py_InitModule("btrack", btrack_methods);
adamstark@51 350 import_array();
adamstark@51 351 }
adamstark@51 352
adamstark@51 353 int main(int argc, char *argv[])
adamstark@51 354 {
adamstark@51 355 /* Pass argv[0] to the Python interpreter */
adamstark@51 356 Py_SetProgramName(argv[0]);
adamstark@51 357
adamstark@51 358 /* Initialize the Python interpreter. Required. */
adamstark@51 359 Py_Initialize();
adamstark@51 360
adamstark@51 361 /* Add a static module */
adamstark@51 362 initbtrack();
adamstark@51 363 }