comparison 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
comparison
equal deleted inserted replaced
54:9699024bb3d0 55:5e520f59127f
2 #include <Python.h> 2 #include <Python.h>
3 #include "../../src/OnsetDetectionFunction.h" 3 #include "../../src/OnsetDetectionFunction.h"
4 #include "../../src/BTrack.h" 4 #include "../../src/BTrack.h"
5 #include <numpy/arrayobject.h> 5 #include <numpy/arrayobject.h>
6 6
7 //=======================================================================
7 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args) 8 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args)
8 { 9 {
9 PyObject *arg1=NULL; 10 PyObject *arg1=NULL;
10 PyObject *arr1=NULL; 11 PyObject *arr1=NULL;
11 12
27 // get data as array 28 // get data as array
28 double* data = (double*) PyArray_DATA(arr1); 29 double* data = (double*) PyArray_DATA(arr1);
29 30
30 // get array size 31 // get array size
31 long signal_length = PyArray_Size((PyObject*)arr1); 32 long signal_length = PyArray_Size((PyObject*)arr1);
32 //int k = (int) theSize;
33
34 // get data type
35 //char type = PyArray_DESCR(arr1)->type;
36 33
37 ////////// BEGIN PROCESS /////////////////// 34 ////////// BEGIN PROCESS ///////////////////
38 int hsize = 512; 35 int hopSize = 512;
39 int fsize = 1024; 36 int frameSize = 1024;
40 int df_type = 6; 37 int df_type = 6;
41 int numframes; 38 int numframes;
42 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples 39 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
43 40
44 41
45 // get number of audio frames, given the hop size and signal length 42 // get number of audio frames, given the hop size and signal length
46 numframes = (int) floor(((double) signal_length) / ((double) hsize)); 43 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
47 44
48 OnsetDetectionFunction onset(hsize,fsize,df_type,1); 45 OnsetDetectionFunction onset(hopSize,frameSize,df_type,1);
49 46
50 double df[numframes]; 47 double df[numframes];
51 48
52 49
53 50
55 //////// Begin Processing Loop //////////// 52 //////// Begin Processing Loop ////////////
56 53
57 for (int i=0;i < numframes;i++) 54 for (int i=0;i < numframes;i++)
58 { 55 {
59 // add new samples to frame 56 // add new samples to frame
60 for (int n = 0;n < hsize;n++) 57 for (int n = 0;n < hopSize;n++)
61 { 58 {
62 buffer[n] = data[(i*hsize)+n]; 59 buffer[n] = data[(i*hopSize)+n];
63 } 60 }
64 61
65 df[i] = onset.getDFsample(buffer); 62 df[i] = onset.getDFsample(buffer);
66 63
67 } 64 }
89 Py_DECREF(arr1); 86 Py_DECREF(arr1);
90 Py_INCREF(Py_None); 87 Py_INCREF(Py_None);
91 //return Py_None; 88 //return Py_None;
92 89
93 return (PyObject *)c; 90 return (PyObject *)c;
94 91 }
95 //return Py_BuildValue("c", type); 92
96 //return Py_BuildValue("d", sum); 93 //=======================================================================
97 //return Py_BuildValue("i", k);
98 /*
99 fail:
100 Py_XDECREF(arr1);
101 Py_XDECREF(arr2);
102 PyArray_XDECREF_ERR(oarr);
103 return NULL;*/
104 }
105
106
107 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args) 94 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args)
108 { 95 {
109 PyObject *arg1=NULL; 96 PyObject *arg1=NULL;
110 PyObject *arr1=NULL; 97 PyObject *arr1=NULL;
111 98
127 // get data as array 114 // get data as array
128 double* data = (double*) PyArray_DATA(arr1); 115 double* data = (double*) PyArray_DATA(arr1);
129 116
130 // get array size 117 // get array size
131 long signal_length = PyArray_Size((PyObject*)arr1); 118 long signal_length = PyArray_Size((PyObject*)arr1);
132 //int k = (int) theSize; 119
133
134 // get data type
135 //char type = PyArray_DESCR(arr1)->type;
136 120
137 ////////// BEGIN PROCESS /////////////////// 121 ////////// BEGIN PROCESS ///////////////////
138 int hsize = 512; 122 int hopSize = 512;
139 int fsize = 1024; 123 int frameSize = 1024;
140 int df_type = 6; 124
141 int numframes; 125 int numframes;
142 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples 126 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
143 127
144 128
145 // get number of audio frames, given the hop size and signal length 129 // get number of audio frames, given the hop size and signal length
146 numframes = (int) floor(((double) signal_length) / ((double) hsize)); 130 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
147 131
148 OnsetDetectionFunction onset(hsize,fsize,df_type,1); 132
149 BTrack b; 133 BTrack b(hopSize,frameSize);
150 134
151 b.initialise((int) hsize); // initialise beat tracker 135
152
153 // set parameters
154 //b.setparams(0.9,5);
155
156 double df[numframes];
157 double beats[5000]; 136 double beats[5000];
158 int beatnum = 0; 137 int beatnum = 0;
159
160 double df_val;
161 138
162 /////////////////////////////////////////// 139 ///////////////////////////////////////////
163 //////// Begin Processing Loop //////////// 140 //////// Begin Processing Loop ////////////
164 141
165 for (int i=0;i < numframes;i++) 142 for (int i=0;i < numframes;i++)
166 { 143 {
167 // add new samples to frame 144 // add new samples to frame
168 for (int n = 0;n < hsize;n++) 145 for (int n = 0;n < hopSize;n++)
169 { 146 {
170 buffer[n] = data[(i*hsize)+n]; 147 buffer[n] = data[(i*hopSize)+n];
171 } 148 }
172 149
173 df[i] = onset.getDFsample(buffer); 150 // process the current audio frame
151 b.processAudioFrame(buffer);
174 152
175 df_val = df[i] + 0.0001; 153 // if a beat is currently scheduled
176
177 b.process(df_val); // process df sample in beat tracker
178
179 if (b.playbeat == 1) 154 if (b.playbeat == 1)
180 { 155 {
181 beats[beatnum] = (((double) hsize) / 44100) * ((double) i); 156 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i);
182 beatnum = beatnum + 1; 157 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
158 beatnum = beatnum + 1;
183 } 159 }
184 160
185 } 161 }
186 162
187 ///////// End Processing Loop ///////////// 163 ///////// End Processing Loop /////////////
215 Py_DECREF(arr1); 191 Py_DECREF(arr1);
216 Py_INCREF(Py_None); 192 Py_INCREF(Py_None);
217 //return Py_None; 193 //return Py_None;
218 194
219 return (PyObject *)c; 195 return (PyObject *)c;
220 196 }
221 //return Py_BuildValue("c", type); 197
222 //return Py_BuildValue("d", sum); 198 //=======================================================================
223 //return Py_BuildValue("i", k);
224 /*
225 fail:
226 Py_XDECREF(arr1);
227 Py_XDECREF(arr2);
228 PyArray_XDECREF_ERR(oarr);
229 return NULL;*/
230 }
231
232 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args) 199 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args)
233 { 200 {
234 PyObject *arg1=NULL; 201 PyObject *arg1=NULL;
235 PyObject *arr1=NULL; 202 PyObject *arr1=NULL;
236 203
252 // get data as array 219 // get data as array
253 double* data = (double*) PyArray_DATA(arr1); 220 double* data = (double*) PyArray_DATA(arr1);
254 221
255 // get array size 222 // get array size
256 long numframes = PyArray_Size((PyObject*)arr1); 223 long numframes = PyArray_Size((PyObject*)arr1);
257 //int k = (int) theSize; 224
258
259 // get data type
260 //char type = PyArray_DESCR(arr1)->type;
261
262 ////////// BEGIN PROCESS /////////////////// 225 ////////// BEGIN PROCESS ///////////////////
263 int hsize = 512; 226 int hopSize = 512;
264 227 int frameSize = 2*hopSize;
265 BTrack b; 228
266 229 BTrack b(hopSize,frameSize);
267 b.initialise((int) hsize); // initialise beat tracker
268
269 // set parameters
270 //b.setparams(0.9,5);
271 230
272 double beats[5000]; 231 double beats[5000];
273 int beatnum = 0; 232 int beatnum = 0;
274 double df_val; 233 double df_val;
275 234
278 237
279 for (long i=0;i < numframes;i++) 238 for (long i=0;i < numframes;i++)
280 { 239 {
281 df_val = data[i] + 0.0001; 240 df_val = data[i] + 0.0001;
282 241
283 b.process(df_val); // process df sample in beat tracker 242 b.processOnsetDetectionFunctionSample(df_val); // process df sample in beat tracker
284 243
285 if (b.playbeat == 1) 244 if (b.playbeat == 1)
286 { 245 {
287 beats[beatnum] = (((double) hsize) / 44100) * ((double) i); 246 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i);
247 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
288 beatnum = beatnum + 1; 248 beatnum = beatnum + 1;
289 } 249 }
290 250
291 } 251 }
292 252
321 Py_DECREF(arr1); 281 Py_DECREF(arr1);
322 Py_INCREF(Py_None); 282 Py_INCREF(Py_None);
323 //return Py_None; 283 //return Py_None;
324 284
325 return (PyObject *)c; 285 return (PyObject *)c;
326 286 }
327 //return Py_BuildValue("c", type); 287
328 //return Py_BuildValue("d", sum); 288
329 //return Py_BuildValue("i", k); 289 //=======================================================================
330 /*
331 fail:
332 Py_XDECREF(arr1);
333 Py_XDECREF(arr2);
334 PyArray_XDECREF_ERR(oarr);
335 return NULL;*/
336 }
337
338
339
340 static PyMethodDef btrack_methods[] = { 290 static PyMethodDef btrack_methods[] = {
341 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"}, 291 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"},
342 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"}, 292 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"},
343 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"}, 293 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"},
344 {NULL, NULL, 0, NULL} /* Sentinel */ 294 {NULL, NULL, 0, NULL} /* Sentinel */
345 }; 295 };
346 296
297 //=======================================================================
347 PyMODINIT_FUNC initbtrack(void) 298 PyMODINIT_FUNC initbtrack(void)
348 { 299 {
349 (void)Py_InitModule("btrack", btrack_methods); 300 (void)Py_InitModule("btrack", btrack_methods);
350 import_array(); 301 import_array();
351 } 302 }
352 303
304 //=======================================================================
353 int main(int argc, char *argv[]) 305 int main(int argc, char *argv[])
354 { 306 {
355 /* Pass argv[0] to the Python interpreter */ 307 /* Pass argv[0] to the Python interpreter */
356 Py_SetProgramName(argv[0]); 308 Py_SetProgramName(argv[0]);
357 309