annotate modules-and-plug-ins/python-module/btrack_python_module.cpp @ 55:5e520f59127f

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 Stark <adamstark@users.noreply.github.com>
date Wed, 22 Jan 2014 18:47:16 +0000
parents 9699024bb3d0
children baf35f208814
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@51 154 if (b.playbeat == 1)
adamstark@51 155 {
adamstark@55 156 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i);
adamstark@55 157 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@55 158 beatnum = beatnum + 1;
adamstark@51 159 }
adamstark@51 160
adamstark@51 161 }
adamstark@51 162
adamstark@51 163 ///////// End Processing Loop /////////////
adamstark@51 164 ///////////////////////////////////////////
adamstark@51 165
adamstark@51 166
adamstark@51 167 ////////// END PROCESS ///////////////////
adamstark@51 168
adamstark@51 169 double beats_out[beatnum]; // create output array
adamstark@51 170
adamstark@51 171 // copy beats into output array
adamstark@51 172 for (int i = 0;i < beatnum;i++)
adamstark@51 173 {
adamstark@51 174 beats_out[i] = beats[i];
adamstark@51 175 }
adamstark@51 176
adamstark@51 177
adamstark@51 178
adamstark@51 179 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 180 int nd=1;
adamstark@51 181 npy_intp m= beatnum;
adamstark@51 182 //double fArray[5] = {0,1,2,3,4};
adamstark@51 183
adamstark@51 184 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 185
adamstark@51 186 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 187
adamstark@51 188 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 189
adamstark@51 190
adamstark@51 191 Py_DECREF(arr1);
adamstark@51 192 Py_INCREF(Py_None);
adamstark@51 193 //return Py_None;
adamstark@51 194
adamstark@51 195 return (PyObject *)c;
adamstark@51 196 }
adamstark@51 197
adamstark@55 198 //=======================================================================
adamstark@51 199 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args)
adamstark@51 200 {
adamstark@51 201 PyObject *arg1=NULL;
adamstark@51 202 PyObject *arr1=NULL;
adamstark@51 203
adamstark@51 204 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 205 {
adamstark@51 206 return NULL;
adamstark@51 207 }
adamstark@51 208
adamstark@51 209 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 210 if (arr1 == NULL)
adamstark@51 211 {
adamstark@51 212 return NULL;
adamstark@51 213 }
adamstark@51 214
adamstark@51 215
adamstark@51 216
adamstark@51 217 ////////// GET INPUT DATA ///////////////////
adamstark@51 218
adamstark@51 219 // get data as array
adamstark@51 220 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 221
adamstark@51 222 // get array size
adamstark@52 223 long numframes = PyArray_Size((PyObject*)arr1);
adamstark@55 224
adamstark@51 225 ////////// BEGIN PROCESS ///////////////////
adamstark@55 226 int hopSize = 512;
adamstark@55 227 int frameSize = 2*hopSize;
adamstark@51 228
adamstark@55 229 BTrack b(hopSize,frameSize);
adamstark@51 230
adamstark@51 231 double beats[5000];
adamstark@51 232 int beatnum = 0;
adamstark@54 233 double df_val;
adamstark@51 234
adamstark@51 235 ///////////////////////////////////////////
adamstark@51 236 //////// Begin Processing Loop ////////////
adamstark@51 237
adamstark@52 238 for (long i=0;i < numframes;i++)
adamstark@51 239 {
adamstark@54 240 df_val = data[i] + 0.0001;
adamstark@51 241
adamstark@55 242 b.processOnsetDetectionFunctionSample(df_val); // process df sample in beat tracker
adamstark@51 243
adamstark@51 244 if (b.playbeat == 1)
adamstark@51 245 {
adamstark@55 246 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i);
adamstark@55 247 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@51 248 beatnum = beatnum + 1;
adamstark@51 249 }
adamstark@51 250
adamstark@51 251 }
adamstark@51 252
adamstark@51 253 ///////// End Processing Loop /////////////
adamstark@51 254 ///////////////////////////////////////////
adamstark@51 255
adamstark@51 256
adamstark@51 257 ////////// END PROCESS ///////////////////
adamstark@51 258
adamstark@51 259 double beats_out[beatnum]; // create output array
adamstark@51 260
adamstark@51 261
adamstark@51 262 // copy beats into output array
adamstark@51 263 for (int i = 0;i < beatnum;i++)
adamstark@51 264 {
adamstark@51 265 beats_out[i] = beats[i];
adamstark@51 266 }
adamstark@51 267
adamstark@51 268
adamstark@51 269 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 270 int nd=1;
adamstark@51 271 npy_intp m= beatnum;
adamstark@51 272 //double fArray[5] = {0,1,2,3,4};
adamstark@51 273
adamstark@51 274 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 275
adamstark@51 276 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 277
adamstark@51 278 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 279
adamstark@51 280
adamstark@51 281 Py_DECREF(arr1);
adamstark@51 282 Py_INCREF(Py_None);
adamstark@51 283 //return Py_None;
adamstark@51 284
adamstark@51 285 return (PyObject *)c;
adamstark@51 286 }
adamstark@51 287
adamstark@51 288
adamstark@55 289 //=======================================================================
adamstark@51 290 static PyMethodDef btrack_methods[] = {
adamstark@51 291 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"},
adamstark@51 292 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"},
adamstark@51 293 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"},
adamstark@51 294 {NULL, NULL, 0, NULL} /* Sentinel */
adamstark@51 295 };
adamstark@51 296
adamstark@55 297 //=======================================================================
adamstark@51 298 PyMODINIT_FUNC initbtrack(void)
adamstark@51 299 {
adamstark@51 300 (void)Py_InitModule("btrack", btrack_methods);
adamstark@51 301 import_array();
adamstark@51 302 }
adamstark@51 303
adamstark@55 304 //=======================================================================
adamstark@51 305 int main(int argc, char *argv[])
adamstark@51 306 {
adamstark@51 307 /* Pass argv[0] to the Python interpreter */
adamstark@51 308 Py_SetProgramName(argv[0]);
adamstark@51 309
adamstark@51 310 /* Initialize the Python interpreter. Required. */
adamstark@51 311 Py_Initialize();
adamstark@51 312
adamstark@51 313 /* Add a static module */
adamstark@51 314 initbtrack();
adamstark@51 315 }