annotate modules-and-plug-ins/python-module/btrack_python_module.cpp @ 57:296af6af6c3d

Replaced switch statements in OnsetDetectionFunction with enums. Renamed lots of functions so that they have better names, in camel case. Added some unit tests for initialisation of BTrack.
author Adam Stark <adamstark@users.noreply.github.com>
date Thu, 23 Jan 2014 15:31:11 +0000
parents 5e520f59127f
children a8e3e95d14e4
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@55 7 //=======================================================================
adamstark@51 8 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args)
adamstark@51 9 {
adamstark@51 10 PyObject *arg1=NULL;
adamstark@51 11 PyObject *arr1=NULL;
adamstark@51 12
adamstark@51 13 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 14 {
adamstark@51 15 return NULL;
adamstark@51 16 }
adamstark@51 17
adamstark@51 18 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 19 if (arr1 == NULL)
adamstark@51 20 {
adamstark@51 21 return NULL;
adamstark@51 22 }
adamstark@51 23
adamstark@51 24
adamstark@51 25
adamstark@51 26 ////////// GET INPUT DATA ///////////////////
adamstark@51 27
adamstark@51 28 // get data as array
adamstark@51 29 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 30
adamstark@51 31 // get array size
adamstark@52 32 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@51 33
adamstark@51 34 ////////// BEGIN PROCESS ///////////////////
adamstark@55 35 int hopSize = 512;
adamstark@55 36 int frameSize = 1024;
adamstark@51 37 int df_type = 6;
adamstark@51 38 int numframes;
adamstark@55 39 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
adamstark@51 40
adamstark@51 41
adamstark@51 42 // get number of audio frames, given the hop size and signal length
adamstark@55 43 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
adamstark@51 44
adamstark@55 45 OnsetDetectionFunction onset(hopSize,frameSize,df_type,1);
adamstark@51 46
adamstark@51 47 double df[numframes];
adamstark@51 48
adamstark@51 49
adamstark@51 50
adamstark@51 51 ///////////////////////////////////////////
adamstark@51 52 //////// Begin Processing Loop ////////////
adamstark@51 53
adamstark@51 54 for (int i=0;i < numframes;i++)
adamstark@51 55 {
adamstark@51 56 // add new samples to frame
adamstark@55 57 for (int n = 0;n < hopSize;n++)
adamstark@51 58 {
adamstark@55 59 buffer[n] = data[(i*hopSize)+n];
adamstark@51 60 }
adamstark@51 61
adamstark@51 62 df[i] = onset.getDFsample(buffer);
adamstark@51 63
adamstark@51 64 }
adamstark@51 65
adamstark@51 66 ///////// End Processing Loop /////////////
adamstark@51 67 ///////////////////////////////////////////
adamstark@51 68
adamstark@51 69
adamstark@51 70 ////////// END PROCESS ///////////////////
adamstark@51 71
adamstark@51 72
adamstark@51 73
adamstark@51 74 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 75 int nd=1;
adamstark@51 76 npy_intp m= numframes;
adamstark@51 77 //double fArray[5] = {0,1,2,3,4};
adamstark@51 78
adamstark@51 79 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 80
adamstark@51 81 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 82
adamstark@51 83 memcpy(arr_data, df, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 84
adamstark@51 85
adamstark@51 86 Py_DECREF(arr1);
adamstark@51 87 Py_INCREF(Py_None);
adamstark@51 88 //return Py_None;
adamstark@51 89
adamstark@51 90 return (PyObject *)c;
adamstark@51 91 }
adamstark@51 92
adamstark@55 93 //=======================================================================
adamstark@51 94 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args)
adamstark@51 95 {
adamstark@51 96 PyObject *arg1=NULL;
adamstark@51 97 PyObject *arr1=NULL;
adamstark@51 98
adamstark@51 99 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 100 {
adamstark@51 101 return NULL;
adamstark@51 102 }
adamstark@51 103
adamstark@51 104 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 105 if (arr1 == NULL)
adamstark@51 106 {
adamstark@51 107 return NULL;
adamstark@51 108 }
adamstark@51 109
adamstark@51 110
adamstark@51 111
adamstark@51 112 ////////// GET INPUT DATA ///////////////////
adamstark@51 113
adamstark@51 114 // get data as array
adamstark@51 115 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 116
adamstark@51 117 // get array size
adamstark@52 118 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@55 119
adamstark@51 120
adamstark@51 121 ////////// BEGIN PROCESS ///////////////////
adamstark@55 122 int hopSize = 512;
adamstark@55 123 int frameSize = 1024;
adamstark@55 124
adamstark@51 125 int numframes;
adamstark@55 126 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
adamstark@51 127
adamstark@51 128
adamstark@51 129 // get number of audio frames, given the hop size and signal length
adamstark@55 130 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
adamstark@51 131
adamstark@55 132
adamstark@55 133 BTrack b(hopSize,frameSize);
adamstark@51 134
adamstark@51 135
adamstark@51 136 double beats[5000];
adamstark@51 137 int beatnum = 0;
adamstark@51 138
adamstark@51 139 ///////////////////////////////////////////
adamstark@51 140 //////// Begin Processing Loop ////////////
adamstark@51 141
adamstark@51 142 for (int i=0;i < numframes;i++)
adamstark@51 143 {
adamstark@51 144 // add new samples to frame
adamstark@55 145 for (int n = 0;n < hopSize;n++)
adamstark@51 146 {
adamstark@55 147 buffer[n] = data[(i*hopSize)+n];
adamstark@51 148 }
adamstark@51 149
adamstark@55 150 // process the current audio frame
adamstark@55 151 b.processAudioFrame(buffer);
adamstark@51 152
adamstark@55 153 // if a beat is currently scheduled
adamstark@57 154 if (b.beatDueInCurrentFrame())
adamstark@51 155 {
adamstark@55 156 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@55 157 beatnum = beatnum + 1;
adamstark@51 158 }
adamstark@51 159
adamstark@51 160 }
adamstark@51 161
adamstark@51 162 ///////// End Processing Loop /////////////
adamstark@51 163 ///////////////////////////////////////////
adamstark@51 164
adamstark@51 165
adamstark@51 166 ////////// END PROCESS ///////////////////
adamstark@51 167
adamstark@51 168 double beats_out[beatnum]; // create output array
adamstark@51 169
adamstark@51 170 // copy beats into output array
adamstark@51 171 for (int i = 0;i < beatnum;i++)
adamstark@51 172 {
adamstark@51 173 beats_out[i] = beats[i];
adamstark@51 174 }
adamstark@51 175
adamstark@51 176
adamstark@51 177
adamstark@51 178 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 179 int nd=1;
adamstark@51 180 npy_intp m= beatnum;
adamstark@51 181 //double fArray[5] = {0,1,2,3,4};
adamstark@51 182
adamstark@51 183 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 184
adamstark@51 185 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 186
adamstark@51 187 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 188
adamstark@51 189
adamstark@51 190 Py_DECREF(arr1);
adamstark@51 191 Py_INCREF(Py_None);
adamstark@51 192 //return Py_None;
adamstark@51 193
adamstark@51 194 return (PyObject *)c;
adamstark@51 195 }
adamstark@51 196
adamstark@55 197 //=======================================================================
adamstark@51 198 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args)
adamstark@51 199 {
adamstark@51 200 PyObject *arg1=NULL;
adamstark@51 201 PyObject *arr1=NULL;
adamstark@51 202
adamstark@51 203 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 204 {
adamstark@51 205 return NULL;
adamstark@51 206 }
adamstark@51 207
adamstark@51 208 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 209 if (arr1 == NULL)
adamstark@51 210 {
adamstark@51 211 return NULL;
adamstark@51 212 }
adamstark@51 213
adamstark@51 214
adamstark@51 215
adamstark@51 216 ////////// GET INPUT DATA ///////////////////
adamstark@51 217
adamstark@51 218 // get data as array
adamstark@51 219 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 220
adamstark@51 221 // get array size
adamstark@52 222 long numframes = PyArray_Size((PyObject*)arr1);
adamstark@55 223
adamstark@51 224 ////////// BEGIN PROCESS ///////////////////
adamstark@55 225 int hopSize = 512;
adamstark@55 226 int frameSize = 2*hopSize;
adamstark@51 227
adamstark@55 228 BTrack b(hopSize,frameSize);
adamstark@51 229
adamstark@51 230 double beats[5000];
adamstark@51 231 int beatnum = 0;
adamstark@54 232 double df_val;
adamstark@51 233
adamstark@51 234 ///////////////////////////////////////////
adamstark@51 235 //////// Begin Processing Loop ////////////
adamstark@51 236
adamstark@52 237 for (long i=0;i < numframes;i++)
adamstark@51 238 {
adamstark@54 239 df_val = data[i] + 0.0001;
adamstark@51 240
adamstark@55 241 b.processOnsetDetectionFunctionSample(df_val); // process df sample in beat tracker
adamstark@51 242
adamstark@57 243 if (b.beatDueInCurrentFrame())
adamstark@51 244 {
adamstark@55 245 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@51 246 beatnum = beatnum + 1;
adamstark@51 247 }
adamstark@51 248
adamstark@51 249 }
adamstark@51 250
adamstark@51 251 ///////// End Processing Loop /////////////
adamstark@51 252 ///////////////////////////////////////////
adamstark@51 253
adamstark@51 254
adamstark@51 255 ////////// END PROCESS ///////////////////
adamstark@51 256
adamstark@51 257 double beats_out[beatnum]; // create output array
adamstark@51 258
adamstark@51 259
adamstark@51 260 // copy beats into output array
adamstark@51 261 for (int i = 0;i < beatnum;i++)
adamstark@51 262 {
adamstark@51 263 beats_out[i] = beats[i];
adamstark@51 264 }
adamstark@51 265
adamstark@51 266
adamstark@51 267 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 268 int nd=1;
adamstark@51 269 npy_intp m= beatnum;
adamstark@51 270 //double fArray[5] = {0,1,2,3,4};
adamstark@51 271
adamstark@51 272 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 273
adamstark@51 274 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 275
adamstark@51 276 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 277
adamstark@51 278
adamstark@51 279 Py_DECREF(arr1);
adamstark@51 280 Py_INCREF(Py_None);
adamstark@51 281 //return Py_None;
adamstark@51 282
adamstark@51 283 return (PyObject *)c;
adamstark@51 284 }
adamstark@51 285
adamstark@51 286
adamstark@55 287 //=======================================================================
adamstark@51 288 static PyMethodDef btrack_methods[] = {
adamstark@51 289 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"},
adamstark@51 290 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"},
adamstark@51 291 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"},
adamstark@51 292 {NULL, NULL, 0, NULL} /* Sentinel */
adamstark@51 293 };
adamstark@51 294
adamstark@55 295 //=======================================================================
adamstark@51 296 PyMODINIT_FUNC initbtrack(void)
adamstark@51 297 {
adamstark@51 298 (void)Py_InitModule("btrack", btrack_methods);
adamstark@51 299 import_array();
adamstark@51 300 }
adamstark@51 301
adamstark@55 302 //=======================================================================
adamstark@51 303 int main(int argc, char *argv[])
adamstark@51 304 {
adamstark@51 305 /* Pass argv[0] to the Python interpreter */
adamstark@51 306 Py_SetProgramName(argv[0]);
adamstark@51 307
adamstark@51 308 /* Initialize the Python interpreter. Required. */
adamstark@51 309 Py_Initialize();
adamstark@51 310
adamstark@51 311 /* Add a static module */
adamstark@51 312 initbtrack();
adamstark@51 313 }