annotate modules-and-plug-ins/python-module/btrack_python_module.cpp @ 18:450c53430540 develop

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