Mercurial > hg > btrack
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 |